blob: 71d0601fe4904dc88261613468721d2f36b67773 [file]
/*
* 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 {
AppConfig,
CamelStatus,
ContainerImage,
ContainerStatus,
DeploymentStatus,
DesignerTab,
FileOperation,
Project,
ProjectFile,
ProjectOperation,
ServiceStatus
} from "./ProjectModels";
import {ProjectEventBus} from "./ProjectEventBus";
import {unstable_batchedUpdates} from "react-dom";
import {createWithEqualityFn} from "zustand/traditional";
import {shallow} from "zustand/shallow";
interface AppConfigState {
loading: boolean;
setLoading: (loading: boolean) => void;
config: AppConfig;
setConfig: (config: AppConfig) => void;
readiness: any;
setReadiness: (readiness: any) => void;
selectedEnv: string[];
setSelectedEnv: (selectedEnv: string[]) => void;
selectEnvironment: (name: string, selected: boolean) => void;
dockerInfo: any;
setDockerInfo: (info: any) => void;
}
export const useAppConfigStore = createWithEqualityFn<AppConfigState>((set) => ({
loading: false,
setLoading: (loading: boolean) => {
set({loading: loading})
},
config: new AppConfig(),
setConfig: (config: AppConfig) => {
set({config: config})
},
readiness: undefined,
setReadiness: (r: any) => {
set((state: AppConfigState) => {
if (JSON.stringify(r) !== JSON.stringify(state?.readiness)) {
return ({readiness: r})
} else {
return ({readiness: state.readiness})
}
});
},
selectedEnv: [],
setSelectedEnv: (selectedEnv: string[]) => {
set((state: AppConfigState) => {
state.selectedEnv.length = 0;
state.selectedEnv.push(...selectedEnv);
return {selectedEnv: state.selectedEnv};
});
},
selectEnvironment(name: string, selected: boolean) {
set((state: AppConfigState) => {
if (selected && !state.selectedEnv.includes(name)) {
state.selectedEnv.push(name);
} else if (!selected && state.selectedEnv.includes(name)) {
const filtered = state.selectedEnv.filter(e => e !== name);
state.selectedEnv.length = 0;
state.selectedEnv.push(...filtered);
}
return {selectedEnv: state.selectedEnv};
});
},
dockerInfo: {},
setDockerInfo: (info: any) => {
set({
dockerInfo: info
})
},
}), shallow)
interface ProjectsState {
projects: Project[];
setProjects: (projects: Project[]) => void;
upsertProject: (project: Project) => void;
filter: string;
setFilter: (filter: string) => void;
}
export const useProjectsStore = createWithEqualityFn<ProjectsState>((set) => ({
projects: [],
setProjects: (ps: Project[]) => {
set((state: ProjectsState) => ({
projects: ps,
}));
},
upsertProject: (project: Project) => {
set((state: ProjectsState) => ({
projects: state.projects.find(f => f.projectId === project.projectId) === undefined
? [...state.projects, project]
: [...state.projects.filter(f => f.projectId !== project.projectId), project]
}));
},
filter: '',
setFilter: (filter: string) => {
set({filter: filter});
}
}), shallow)
interface ProjectState {
isPulling: boolean,
isPushing: boolean,
isRunning: boolean,
images: ContainerImage [],
setImages: (images: ContainerImage []) => void;
project: Project;
setProject: (project: Project, operation: ProjectOperation) => void;
operation: "create" | "select" | "delete" | "none" | "copy";
tabIndex: string | number;
setTabIndex: (tabIndex: string | number) => void;
setOperation: (o: ProjectOperation) => void;
camelStatuses: CamelStatus[],
setCamelStatuses: (camelStatuses: CamelStatus[]) => void;
camelTraces: CamelStatus[],
setCamelTraces: (camelTraces: CamelStatus[]) => void;
refreshTrace: boolean
setRefreshTrace: (refreshTrace: boolean) => void;
}
export const useProjectStore = createWithEqualityFn<ProjectState>((set) => ({
project: new Project(),
images: [],
operation: 'none',
tabIndex: 'topology',
isPushing: false,
isPulling: false,
isRunning: false,
setProject: (project: Project, operation: ProjectOperation) => {
set((state: ProjectState) => ({
project: project,
operation: operation,
refreshTrace: false,
jvm: {},
context: {},
trace: {},
memory: {},
tabIndex: state.tabIndex
}));
},
setOperation: (o: ProjectOperation) => {
set((state: ProjectState) => ({
operation: o
}));
},
setTabIndex: (tabIndex: string | number) => {
set((state: ProjectState) => {
return {tabIndex: tabIndex};
});
},
setImages: (images: ContainerImage[]) => {
set((state: ProjectState) => {
state.images.length = 0;
state.images.push(...images);
return {images: state.images};
});
},
camelStatuses: [],
setCamelStatuses: (camelStatuses: CamelStatus[]) => {
set((state: ProjectState) => {
return {camelStatuses: camelStatuses};
});
},
camelTraces: [],
setCamelTraces: (camelTraces: CamelStatus[]) => {
set((state: ProjectState) => {
return {camelTraces: camelTraces};
});
},
refreshTrace: false,
setRefreshTrace: (refreshTrace: boolean) => {
set({refreshTrace: refreshTrace})
},
}), shallow)
interface FilesState {
files: ProjectFile[];
diff: any;
setFiles: (files: ProjectFile[]) => void;
upsertFile: (file: ProjectFile) => void;
selectedFileNames: string[];
setSelectedFileNames: (selectedFileNames: string[]) => void;
selectFile: (filename: string) => void;
unselectFile: (filename: string) => void;
}
export const useFilesStore = createWithEqualityFn<FilesState>((set) => ({
files: [],
diff: {},
selectedFileNames: [],
setFiles: (files: ProjectFile[]) => {
set((state: FilesState) => ({
files: files
}));
},
upsertFile: (file: ProjectFile) => {
set((state: FilesState) => ({
files: state.files.find(f => f.name === file.name) === undefined
? [...state.files, file]
: [...state.files.filter(f => f.name !== file.name), file]
}));
},
setSelectedFileNames: (selectedFileNames: string[]) => {
set((state: FilesState) => ({
selectedFileNames: selectedFileNames
}));
},
selectFile: (filename: string) => {
set((state: FilesState) => {
const names = [...state.selectedFileNames];
if (!state.selectedFileNames.includes(filename)) {
names.push(filename);
}
return ({selectedFileNames: names})
});
},
unselectFile: (filename: string) => {
set((state: FilesState) => {
const names = [...state.selectedFileNames.filter(f => f !== filename)];
return ({selectedFileNames: names})
});
}
}), shallow)
interface FileState {
file?: ProjectFile;
operation: FileOperation;
designerTab?: DesignerTab;
setFile: (operation: FileOperation, file?: ProjectFile, designerTab?: DesignerTab) => void;
}
export const useFileStore = createWithEqualityFn<FileState>((set) => ({
file: undefined,
operation: "none",
designerTab: "routes",
addProperty: '',
setFile: (operation: FileOperation, file?: ProjectFile, designerTab?: DesignerTab) => {
set((state: FileState) => ({
file: file,
operation: operation,
designerTab: designerTab
}));
},
}), shallow)
interface WizardState {
showWizard: boolean;
setShowWizard: (showWizard: boolean) => void;
}
export const useWizardStore = createWithEqualityFn<WizardState>((set) => ({
showWizard: false,
setShowWizard: (showWizard: boolean) => {
set({showWizard: showWizard})
},
}), shallow)
interface DevModeState {
podName?: string,
status: "none" | "wip",
setStatus: (status: "none" | "wip") => void,
setPodName: (podName?: string) => void,
}
export const useDevModeStore = createWithEqualityFn<DevModeState>((set) => ({
podName: undefined,
status: "none",
setStatus: (status: "none" | "wip") => {
set((state: DevModeState) => ({
status: status,
}));
},
setPodName: (podName?: string) => {
set((state: DevModeState) => ({
podName: podName,
}));
},
}), shallow)
interface StatusesState {
deployments: DeploymentStatus[];
services: ServiceStatus[];
containers: ContainerStatus[];
camelContexts: CamelStatus[];
routes: CamelStatus[];
setRoutes: (routes: CamelStatus[]) => void;
consumers: CamelStatus[];
setConsumers: (consumers: CamelStatus[]) => void;
processors: CamelStatus[];
setProcessors: (processors: CamelStatus[]) => void;
setDeployments: (d: DeploymentStatus[]) => void;
setServices: (s: ServiceStatus[]) => void;
setContainers: (c: ContainerStatus[]) => void;
setCamelContexts: (camelContexts: CamelStatus[]) => void;
}
export const useStatusesStore = createWithEqualityFn<StatusesState>((set) => ({
deployments: [],
services: [],
containers: [],
camelContexts: [],
routes: [],
consumers: [],
processors: [],
setDeployments: (d: DeploymentStatus[]) => {
set((state: StatusesState) => ({
deployments: d,
}));
},
setServices: (s: ServiceStatus[]) => {
set((state: StatusesState) => ({
services: s,
}));
},
setContainers: (c: ContainerStatus[]) => {
set((state: StatusesState) => ({
containers: c,
}));
},
setCamelContexts: (c: CamelStatus[]) => {
set((state: StatusesState) => ({
camelContexts: c,
}));
},
setRoutes: (routes: CamelStatus[]) => {
set((state: StatusesState) => ({
routes: routes,
}));
},
setConsumers: (consumers: CamelStatus[]) => {
set({consumers})
},
setProcessors: (processors: CamelStatus[]) => {
set({processors})
},
}), shallow)
interface LogState {
podName?: string,
data: string;
setData: (data: string) => void;
addData: (data: string) => void;
addDataAsync: (data: string) => void;
currentLine: number;
setCurrentLine: (currentLine: number) => void;
showLog: boolean,
setShowLog: (showLog: boolean, type: 'container' | 'build' | 'none', podName?: string) => void;
type: 'container' | 'build' | 'none',
setType: (type: 'container' | 'build' | 'none') => void,
}
export const useLogStore = createWithEqualityFn<LogState>((set) => ({
podName: undefined,
data: '',
setData: (data: string) => {
set({data: data})
},
addData: (data: string) => {
set((state: LogState) => {
const delimiter = state.data.endsWith('\n') ? '' : '\n';
return ({data: state.data.concat(delimiter, data)})
})
},
addDataAsync: async (data: string) => {
set((state: LogState) => {
const delimiter = state.data.endsWith('\n') ? '' : '\n';
return ({data: state.data.concat(delimiter, data)})
})
},
currentLine: 0,
setCurrentLine: (currentLine: number) => {
set((state: LogState) => ({currentLine: currentLine}))
},
showLog: false,
setShowLog: (showLog: boolean, type: 'container' | 'build' | 'none', podName?: string) => {
set(() => ({showLog: showLog, type: type, podName: podName}));
},
type: "none",
setType: (type: 'container' | 'build' | 'none') => {
set((state: LogState) => ({type: type}));
},
}), shallow)
const sub = ProjectEventBus.onLog()?.subscribe((result: ["add" | "set", string]) => {
if (result[0] === 'add') {
unstable_batchedUpdates(() => {
useLogStore.setState((state: LogState) => {
const delimiter = state.data.endsWith('\n') ? '' : '\n';
const newData = state.data ? state.data.concat(delimiter, result[1]) : result[1]
return ({data: newData, currentLine: state.currentLine + 1});
})
})
} else if (result[0] === 'set') {
unstable_batchedUpdates(() => {
useLogStore.setState({data: result[1], currentLine: 0});
})
}
});