This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git

commit fa98128d1b1b5921b6f5314a06e808a727f5d812
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Fri Feb 27 16:23:34 2026 -0500

    Front-end Stores for 4.18.0
---
 .../src/karavan/stores/ContainerStatusesStore.ts   | 48 ++++++++++++
 .../src/main/webui/src/karavan/stores/LogStore.ts  | 58 ++++++++++++++
 .../main/webui/src/karavan/stores/SettingsStore.ts | 88 ++++++++++++++++++++++
 .../main/webui/src/karavan/stores/TopologyStore.ts | 63 ++++++++++++++++
 4 files changed, 257 insertions(+)

diff --git 
a/karavan-app/src/main/webui/src/karavan/stores/ContainerStatusesStore.ts 
b/karavan-app/src/main/webui/src/karavan/stores/ContainerStatusesStore.ts
new file mode 100644
index 00000000..8a91f5bd
--- /dev/null
+++ b/karavan-app/src/main/webui/src/karavan/stores/ContainerStatusesStore.ts
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {KaravanApi} from "@api/KaravanApi";
+import {create} from "zustand";
+import {ContainerStatus} from "@models/ProjectModels";
+import isEqual from "lodash/isEqual";
+
+type ContainerStatusesState = {
+    containers: ContainerStatus[];
+    fetchContainers: () => Promise<void>;
+    findContainers: (projectId: string) => ContainerStatus[];
+}
+
+export const useContainerStatusesStore = create<ContainerStatusesState>((set, 
get) => ({
+    containers: [],
+    fetchContainers: async (): Promise<void> => {
+        const currentContainers = get().containers;
+        await new Promise<ContainerStatus[]>((resolve, reject) => {
+            KaravanApi.getAllContainerStatuses((containers: ContainerStatus[]) 
=> {
+                resolve(containers);
+            });
+        })
+            .then((containers) => {
+                if (!isEqual(currentContainers, containers)) {
+                    set({containers: containers});
+                }
+            });
+    },
+    findContainers: (projectId: string) => {
+        const state = get();
+        return state.containers.filter(c => c.projectId === projectId);
+    },
+}))
+
diff --git a/karavan-app/src/main/webui/src/karavan/stores/LogStore.ts 
b/karavan-app/src/main/webui/src/karavan/stores/LogStore.ts
new file mode 100644
index 00000000..65b7d030
--- /dev/null
+++ b/karavan-app/src/main/webui/src/karavan/stores/LogStore.ts
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {ProjectEventBus} from "@bus/ProjectEventBus";
+import {unstable_batchedUpdates} from "react-dom";
+import {createWithEqualityFn} from "zustand/traditional";
+import {shallow} from "zustand/shallow";
+
+const MAX_LOG_LINES = 1000;
+
+interface LogState {
+    podName?: string,
+    data: string[];
+    setData: (data: string[]) => void;
+}
+
+export const useLogStore = createWithEqualityFn<LogState>((set) => ({
+    podName: undefined,
+    data: [],
+    setData: (data: string[]) => {
+        set({data: data})
+    }
+}), shallow)
+
+const sub = ProjectEventBus.onLog()?.subscribe((result: ["add" | "set", 
string]) => {
+    if (result[0] === 'add') {
+        unstable_batchedUpdates(() => {
+            useLogStore.setState((state: LogState) => {
+                const newEntry = result[1]?.length !== 0 ? result[1] : "\n";
+
+                // Combine, then slice from the end (negative index)
+                const newData = [...state.data, newEntry];
+                const trimmedData = newData.length > MAX_LOG_LINES
+                    ? newData.slice(-MAX_LOG_LINES)
+                    : newData;
+
+                return { data: trimmedData };
+            })
+        })
+    } else if (result[0] === 'set') {
+        unstable_batchedUpdates(() => {
+            useLogStore.setState({data: [result[1]]});
+        })
+    }
+});
\ No newline at end of file
diff --git a/karavan-app/src/main/webui/src/karavan/stores/SettingsStore.ts 
b/karavan-app/src/main/webui/src/karavan/stores/SettingsStore.ts
new file mode 100644
index 00000000..33af15fb
--- /dev/null
+++ b/karavan-app/src/main/webui/src/karavan/stores/SettingsStore.ts
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {ProjectFile, ProjectType} from "@models/ProjectModels";
+import {create} from "zustand";
+import {KaravanApi} from "@api/KaravanApi";
+import isEqual from "lodash/isEqual";
+import concat from "lodash/concat";
+
+export const SettingsMenus = ['templates', 'kamelets', 'configuration'] as 
const;
+export type SettingsMenu = typeof SettingsMenus[number];
+
+type SettingsState = {
+    currentMenu: SettingsMenu;
+    setCurrentMenu: (currentMenu: SettingsMenu) => void;
+    selectedProjectId?: string;
+    setSelectedProjectId: (selectedProjectId?: string) => void;
+    selectedFileName?: string;
+    setSelectedFilename: (selectedFileName?: string) => void;
+}
+
+export const useSettingsStore = create<SettingsState>((set, get) => ({
+    currentMenu: SettingsMenus[0],
+    setCurrentMenu: (currentMenu: SettingsMenu) => {
+        set({ currentMenu: currentMenu });
+    },
+    setSelectedProjectId: (selectedProjectId: string) => {
+        set({ selectedProjectId: selectedProjectId });
+    },
+    setSelectedFilename: (selectedFileName: string) => {
+        set({ selectedFileName: selectedFileName });
+    },
+}))
+
+type TemplatesState = {
+    templateFiles: ProjectFile[];
+    saveTemplateFile: (file: ProjectFile) => Promise<void>;
+    fetchTemplateFiles: () => Promise<void>;
+}
+
+export const useTemplatesStore = create<TemplatesState>((set, get) => ({
+    templateFiles: [],
+    fetchTemplateFiles: async (): Promise<void> => {
+        await new Promise<ProjectFile[]>((resolve) => {
+            KaravanApi.getFiles(ProjectType.templates, resolve);
+        }).then(templates => {
+            const currentTemplateFiles = get().templateFiles;
+            if (!isEqual(currentTemplateFiles, templates)) {
+                set({ templateFiles: templates });
+            }
+        })
+    },
+    saveTemplateFile: async (file: ProjectFile) => {
+        const prevSettings = [...get().templateFiles];
+        const newTemplateFiles = concat(prevSettings.filter(f => f.name !== 
file.name), file)
+        set({ templateFiles: newTemplateFiles });
+
+        await new Promise<{ result: boolean; file: ProjectFile | any 
}>((resolve, reject) => {
+            KaravanApi.saveProjectFile(file, (result, file) => {
+                if (result) {
+                    resolve({ result, file });
+                } else {
+                    // Reject the promise if the API explicitly returns 
result: false (Application error)
+                    reject(new Error("API returned failure result."));
+                }
+            });
+        }).catch(error => {
+            set({ templateFiles: prevSettings });
+            console.error(error);
+        });
+    }
+}))
+
+
+
diff --git a/karavan-app/src/main/webui/src/karavan/stores/TopologyStore.ts 
b/karavan-app/src/main/webui/src/karavan/stores/TopologyStore.ts
new file mode 100644
index 00000000..f7088137
--- /dev/null
+++ b/karavan-app/src/main/webui/src/karavan/stores/TopologyStore.ts
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {createWithEqualityFn} from "zustand/traditional";
+
+interface TopologyState {
+    fileName?: string
+    setFileName: (fileName?: string) => void
+    showGroups: boolean
+    setShowGroups: (showGroups: boolean) => void
+    showBeans: boolean
+    setShowBeans: (showBeans: boolean) => void
+    showLegend: boolean
+    setShowLegend: (showLegend: boolean) => void
+    showStats: boolean
+    setShowStats: (showStats: boolean) => void
+}
+
+export const useTopologyStore = createWithEqualityFn<TopologyState>((set, get) 
=> {
+    return {
+        setFileName: (fileName?: string) => {
+            set((state: TopologyState) => {
+                return {fileName: fileName};
+            });
+        },
+        showGroups: false,
+        setShowGroups: (showGroups: boolean) => {
+            set({showGroups: showGroups});
+        },
+        showBeans: false,
+        setShowBeans: (showBeans: boolean) => {
+            set((state: TopologyState) => {
+                return {showBeans: showBeans};
+            });
+        },
+        showLegend: false,
+        setShowLegend: (showLegend: boolean) => {
+            set((state: TopologyState) => {
+                return {showLegend: showLegend};
+            });
+        },
+        showStats: false,
+        setShowStats: (showStats: boolean) => {
+            set((state: TopologyState) => {
+                return {showStats: showStats};
+            });
+        },
+    }
+});

Reply via email to