You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2026/04/03 18:36:57 UTC
(camel-karavan) 13/18: Karavan App Cleanup
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 7eaf19230ee4f1c0bb233281e6caaf03ee4204bf
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Fri Apr 3 14:04:56 2026 -0400
Karavan App Cleanup
---
.../src/main/webui/src/ui/api/ValidationApi.tsx | 66 ---------------
.../DashboardDevelopmentCardProjectRow.tsx | 15 +---
.../DashboardDevelopmentCardProjects.tsx | 1 -
.../development/DashboardDevelopmentHook.tsx | 99 +---------------------
.../development/DashboardDevelopmentRefresher.tsx | 5 +-
.../ui/features/project/ProjectPageNavigation.tsx | 4 -
.../webui/src/ui/features/project/ProjectTitle.tsx | 6 +-
.../project/developer/DeveloperManager.tsx | 5 +-
.../project/developer/DeveloperToolbar.tsx | 75 ----------------
.../ui/features/project/developer/YamlEditor.tsx | 13 ---
.../src/ui/features/project/files/FilesSubTab.tsx | 5 --
.../src/ui/features/project/files/FilesToolbar.tsx | 11 ---
.../project/project-topology/CustomNode.tsx | 14 +--
.../project/project-topology/TopologyToolbar.tsx | 10 +--
.../src/ui/features/projects/ProjectsTableRow.tsx | 4 -
.../main/webui/src/ui/models/ValidationModels.ts | 12 ---
.../main/webui/src/ui/stores/ValidationStore.ts | 40 ---------
17 files changed, 8 insertions(+), 377 deletions(-)
diff --git a/karavan-app/src/main/webui/src/ui/api/ValidationApi.tsx b/karavan-app/src/main/webui/src/ui/api/ValidationApi.tsx
deleted file mode 100644
index 3fe91d4d..00000000
--- a/karavan-app/src/main/webui/src/ui/api/ValidationApi.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import axios from "axios";
-import {AuthApi} from "@api/auth/AuthApi";
-import {ErrorEventBus} from "@bus/ErrorEventBus";
-import {ProjectValidation} from "@models/ValidationModels";
-
-axios.defaults.headers.common['Accept'] = 'application/json';
-axios.defaults.headers.common['Content-Type'] = 'application/json';
-const instance = AuthApi.getInstance();
-
-export class ValidationApi {
-
- static async getAllProjectValidations(after: (result: ProjectValidation[]) => void) {
- instance.get('/ui/validation/')
- .then(res => {
- if (res.status === 200) {
- after(res.data);
- } else {
- after([]);
- }
- }).catch(err => {
- ErrorEventBus.sendApiError(err);
- after([]);
- });
- }
-
- static async validateProjects(after: () => void) {
- instance.post('/ui/validation/', {})
- .then(res => {
- if (res.status === 200) {
- after();
- } else {
- after();
- }
- }).catch(err => {
- ErrorEventBus.sendApiError(err);
- after();
- });
- }
-
- static async validateProject(projectId: string, after: () => void) {
- instance.post(`/ui/validation/project/${projectId}`, {})
- .then(res => {
- if (res.status === 200) {
- after();
- } else {
- after();
- }
- }).catch(err => {
- ErrorEventBus.sendApiError(err);
- after();
- });
- }
- static async validateProjectFile(projectId: string, filename: string, after: () => void) {
- instance.post(`/ui/validation/project/${projectId}/${filename}`, {})
- .then(res => {
- if (res.status === 200) {
- after();
- } else {
- after();
- }
- }).catch(err => {
- ErrorEventBus.sendApiError(err);
- after();
- });
- }
-}
diff --git a/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentCardProjectRow.tsx b/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentCardProjectRow.tsx
index 45c88ac1..fbb59bd3 100644
--- a/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentCardProjectRow.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentCardProjectRow.tsx
@@ -1,12 +1,10 @@
import React from 'react';
-import {Button, Content, Label} from '@patternfly/react-core';
+import {Button, Content} from '@patternfly/react-core';
import {BUILD_IN_PROJECTS, Project, ProjectCommited} from "@models/ProjectModels";
import {ComplexityProject} from "@features/projects/ComplexityModels";
import {ProjectInfo} from "@models/CatalogModels";
import {useNavigate} from "react-router-dom";
-import {useValidationStore} from "@stores/ValidationStore";
import {Td, Tr} from "@patternfly/react-table";
-import CheckCircleIcon from "@patternfly/react-icons/dist/esm/icons/check-circle-icon";
import {ROUTES} from "@app/navigation/Routes";
import {ProjectsTableRowTimeLine} from "@features/projects/ProjectsTableRowTimeLine";
import {ProjectStatusLabel} from "@features/projects/ProjectStatusLabel";
@@ -24,13 +22,8 @@ interface Props {
export function DashboardDevelopmentCardProjectRow(props: Props): React.ReactElement {
- const {validations} = useValidationStore();
const {project, complexity, activeUsers, labels, projectInfo, projectCommited} = props;
const navigate = useNavigate();
- const validation = validations?.find(v => v.projectId === project.projectId);
- const hasErrors = validation?.hasErrors;
- const errorCount = validation?.files?.filter(f => f.hasErrors)?.length || 0;
- const color = hasErrors ? "var(--pf-t--global--icon--color--status--danger--default)" : "var(--pf-t--global--icon--color--status--success--default)"
const isBuildIn = BUILD_IN_PROJECTS.includes(project.projectId);
return (
<Tr key={project.projectId} style={{verticalAlign: "middle"}} className={"project-card"}>
@@ -40,12 +33,6 @@ export function DashboardDevelopmentCardProjectRow(props: Props): React.ReactEle
<div>{project.projectId}</div>
</Button>
</Td>
- <Td textCenter>
- {hasErrors
- ? <Label status={'danger'} variant={'outline'}>{errorCount}</Label>
- : <CheckCircleIcon color={color}/>
- }
- </Td>
<Td modifier={"nowrap"} textCenter>
<ProjectsTableRowTimeLine project={project} projectCommited={projectCommited} />
</Td>
diff --git a/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentCardProjects.tsx b/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentCardProjects.tsx
index 826a2fda..89c450dd 100644
--- a/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentCardProjects.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentCardProjects.tsx
@@ -121,7 +121,6 @@ export function DashboardDevelopmentCardProjects() {
<Th key='project'>
<Content component={'h6'}>Recent Projects</Content>
</Th>
- <Th key='validation' modifier='fitContent' textCenter>Validation</Th>
<Th key='timeline'>
<ProgressStepper isCenterAligned className={"projects-table-header-progress-stepper"}>
<ProgressStep id="commited" titleId="commited">
diff --git a/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentHook.tsx b/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentHook.tsx
index 25eaf94a..ac3f1223 100644
--- a/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentHook.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentHook.tsx
@@ -2,112 +2,16 @@ import {useStatusesStore} from "@stores/ProjectStore";
import {ROUTES} from "@app/navigation/Routes";
import {useNavigate} from "react-router-dom";
import {ProjectMetrics} from "@models/DashboardModels";
-import {useValidationStore} from "@stores/ValidationStore";
-import {Button, Content, Popover, Tooltip} from "@patternfly/react-core";
-import * as React from "react";
-import ExclamationCircleIcon from "@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon";
export function DashboardDevelopmentHook() {
const [camelStatuses] = useStatusesStore((s) => [s.camelContexts])
- const [validations] = useValidationStore((s) => [s.validations])
const navigate = useNavigate();
function selectFile(integration: string, fileName: string) {
navigate(`${ROUTES.PROJECTS}/${integration}/${fileName}`);
}
- function getValidationInfo(projectId: string) {
- return validations.find(v => v.projectId === projectId);
- }
-
- function getValidationInfoForFile(projectId: string, fileName: string) {
- const validation = getValidationInfo(projectId);
- return validation?.files?.find(f => f.name === fileName)
- }
-
- function getProjectValidationIcon(projectId: string) {
- const validation = getValidationInfo(projectId);
- const invalidFiles = validation?.files?.filter(f => f?.hasErrors)?.length ?? 0;
- let labelIcon = undefined;
- if (validation?.hasErrors) {
- labelIcon = (
- <Tooltip content={`Errors in ${invalidFiles} file(s)!`} className={'tooltip-danger'}>
- <ExclamationCircleIcon className='validation-icon validation-icon-danger'/>
- </Tooltip>
- );
- }
- return labelIcon;
- }
-
- function getProjectValidationStatus(projectId: string) {
- const validation = getValidationInfo(projectId);
- const invalidFiles = validation?.files?.filter(f => f?.hasErrors)?.length ?? 0;
- if (validation === undefined || validation === null || validation.files?.length === 0) {
- return undefined;
- } else if (invalidFiles > 0) {
- return false;
- }
- return true;
- }
-
- function getProjectFileValidationIcon(projectId: string, fileName: string) {
- const invalidFile = getValidationInfoForFile(projectId, fileName);
- let labelIcon = undefined;
- if (invalidFile?.hasErrors) {
- labelIcon = (
- <Tooltip content={`Errors in file ${invalidFile?.name}!`} className={'tooltip-danger'}>
- <ExclamationCircleIcon className='validation-icon validation-icon-danger'/>
- </Tooltip>
- );
- }
- return labelIcon;
- }
-
- function getProjectFileValidationAlerts(projectId: string, fileName: string) {
- try {
- const invalidFile = getValidationInfoForFile(projectId, fileName);
- if (invalidFile?.hasErrors) {
- const errors = invalidFile?.errors;
- if (errors && Array.isArray(errors)) {
- return (
- <Popover
- className='popover-file-validation'
- aria-label="Alert popover"
- hasAutoWidth
- alertSeverityVariant={'danger'}
- headerContent="Validation Errors"
- headerIcon={<ExclamationCircleIcon/>}
- headerComponent="h1"
- bodyContent={
- <div style={{display: "flex", flexDirection: "column", justifyContent: "flex-start", alignItems: "stretch", gap: "8px"}}>
- {errors.map((error, index) => {
- const line = error?.details?.line;
- const type = error?.property ? error?.property : error?.type;
- const title = `Error at line ${line}: ${type}`
- return (
- <div key={index} style={{display: "flex", flexDirection: "column", justifyContent: "flex-start", gap: "3px"}}>
- <Content style={{fontWeight: 'bold', margin: 0}} component="p">{title}</Content>
- <Content style={{margin: 0}} component="p">{error?.message}</Content>
- </div>
- )
- })}
- </div>
- }
- appendTo={() => document.body}
- >
- <Button isInline variant={'link'} isDanger icon={<ExclamationCircleIcon/>}>Validation Error</Button>
- </Popover>
- )
- }
- }
- } catch (err) {
- console.error(err);
- }
- return undefined;
- }
-
-
function getIntegrationMetrics(projectId: string): ProjectMetrics {
let remoteExchangesTotal: number = 0;
let remoteExchangesFailed: number = 0;
@@ -142,7 +46,6 @@ export function DashboardDevelopmentHook() {
}
return {
- selectFile, getValidationInfoForFile, getProjectValidationIcon, getProjectFileValidationIcon,
- getProjectFileValidationAlerts, getProjectValidationStatus
+ selectFile
}
}
\ No newline at end of file
diff --git a/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentRefresher.tsx b/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentRefresher.tsx
index 75a96334..87b04495 100644
--- a/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentRefresher.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/dashboard/development/DashboardDevelopmentRefresher.tsx
@@ -7,16 +7,14 @@ import {useDataPolling} from "@shared/polling/useDataPolling";
import {DashboardService} from "@services/DashboardService";
import {INTERNAL_COMPONENTS} from "@core/api/ComponentApi";
import {useContainerStatusesStore} from "@stores/ContainerStatusesStore";
-import {useValidationStore} from "@stores/ValidationStore";
import {useCommitsStore} from "@stores/CommitsStore";
-import {useProjectInfoStore} from "../../../stores/ProjectInfoStore";
+import {useProjectInfoStore} from "@stores/ProjectInfoStore";
export function DashboardDevelopmentRefresher() {
const {containers} = useContainerStatusesStore();
const [consumers, processors] = useStatusesStore((s) => [s.consumers, s.processors]);
const {fetchProjectsCommited} = useProjectsStore();
- const {fetchValidations} = useValidationStore();
const {fetchSystemCommits} = useCommitsStore();
const [projectInfos, fetchProjectInfos] = useProjectInfoStore(s => [s.projectInfos, s.fetchProjectInfos]);
const [count, setCount] = useState<number>(0);
@@ -27,7 +25,6 @@ export function DashboardDevelopmentRefresher() {
function refreshDesign() {
ProjectService.refreshProjects();
- fetchValidations();
fetchSystemCommits();
fetchProjectsCommited();
fetchProjectInfos();
diff --git a/karavan-app/src/main/webui/src/ui/features/project/ProjectPageNavigation.tsx b/karavan-app/src/main/webui/src/ui/features/project/ProjectPageNavigation.tsx
index 8c95fab4..413c9a68 100644
--- a/karavan-app/src/main/webui/src/ui/features/project/ProjectPageNavigation.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/project/ProjectPageNavigation.tsx
@@ -36,7 +36,6 @@ import {TryOutIcon} from "@shared/icons/TryOutIcon";
import {shallow} from "zustand/shallow";
import {useIntegrationStore} from "@features/project/designer/DesignerStore";
import {KubernetesIcon} from "@features/project/designer/icons/ComponentIcons";
-import {DashboardDevelopmentHook} from "@features/dashboard/development/DashboardDevelopmentHook";
export function ProjectPageNavigation(): JSX.Element {
@@ -62,9 +61,6 @@ export function ProjectPageNavigation(): JSX.Element {
const [buildContainerId, setBuildContainerId] = useState<string>('');
const [hasDevMode, setHasDevMode] = useState<boolean>(false);
- const {getProjectValidationIcon} = DashboardDevelopmentHook();
- const validationIcon = getProjectValidationIcon(project?.projectId)
-
useEffect(() => {
selectName();
}, [tabIndex, hasDevmodeContainers, hasBuildContainers, buildContainer?.containerId, buildContainerId])
diff --git a/karavan-app/src/main/webui/src/ui/features/project/ProjectTitle.tsx b/karavan-app/src/main/webui/src/ui/features/project/ProjectTitle.tsx
index 7fa2905a..88616015 100644
--- a/karavan-app/src/main/webui/src/ui/features/project/ProjectTitle.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/project/ProjectTitle.tsx
@@ -19,7 +19,6 @@ import React from 'react';
import {Alert, ClipboardCopy, Content, Flex, FlexItem,} from '@patternfly/react-core';
import {useFileStore, useProjectStore} from "@stores/ProjectStore";
import {shallow} from "zustand/shallow";
-import {GENERATED_FILENAME_PREFIX} from "@models/CatalogModels";
import {LockedIcon} from "@patternfly/react-icons";
export function ProjectTitle() {
@@ -28,7 +27,6 @@ export function ProjectTitle() {
const [file, setFile, operation] = useFileStore((s) => [s.file, s.setFile, s.operation], shallow);
const isFile = file !== undefined && operation !== 'delete';
- const isGenerated = isFile && file?.name?.startsWith(GENERATED_FILENAME_PREFIX);
const isLog = file !== undefined && file.name.endsWith("log");
const filename = file ? file.name.substring(0, file.name.lastIndexOf('.')) : "";
@@ -87,8 +85,8 @@ export function ProjectTitle() {
return (
<div className="dsl-title project-title">
- {isFile && !isGenerated && getFileTitle()}
- {isFile && isGenerated && getGeneratedFileTitle()}
+ {isFile && getFileTitle()}
+ {isFile && getGeneratedFileTitle()}
{!isFile && getProjectTitle()}
</div>
)
diff --git a/karavan-app/src/main/webui/src/ui/features/project/developer/DeveloperManager.tsx b/karavan-app/src/main/webui/src/ui/features/project/developer/DeveloperManager.tsx
index 302d68f7..ad5f7b5c 100644
--- a/karavan-app/src/main/webui/src/ui/features/project/developer/DeveloperManager.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/project/developer/DeveloperManager.tsx
@@ -11,14 +11,11 @@ import {EditorType} from "@features/project/developer/EditorConfig";
import {APPLICATION_PROPERTIES, DOCKER_COMPOSE, DOCKER_STACK, KUBERNETES_YAML} from "@models/ProjectModels";
import DeveloperToolbar from "@features/project/developer/DeveloperToolbar";
import {DesignerEditor} from "@features/project/developer/DesignerEditor";
-import {DashboardDevelopmentHook} from "@features/dashboard/development/DashboardDevelopmentHook";
export function DeveloperManager() {
const [file] = useFileStore((s) => [s.file], shallow)
const [designerSwitch, setDesignerSwitch] = useDesignerStore((s) => [s.designerSwitch, s.setDesignerSwitch], shallow)
- const {getValidationInfoForFile} = DashboardDevelopmentHook();
- const validation = getValidationInfoForFile(file.projectId, file?.name);
useEffect(() => {
if (isCamelYaml || isKameletYaml) {
@@ -43,7 +40,7 @@ export function DeveloperManager() {
const isCamelYaml = yamlIsCamel();
const isKameletYaml = file?.name.endsWith(".kamelet.yaml");
const isIntegration = isCamelYaml && (file?.code && CamelDefinitionYaml.yamlIsIntegration(file.code) || file?.code?.length === 0);
- const showDesigner = !validation?.hasErrors && designerSwitch && ((isCamelYaml && isIntegration) || isKameletYaml);
+ const showDesigner = designerSwitch && ((isCamelYaml && isIntegration) || isKameletYaml);
const showPropertiesEditor = file?.name === APPLICATION_PROPERTIES;
const isMarkdown = file?.name.endsWith(".md");
const isGroovy = file?.name.endsWith(".groovy");
diff --git a/karavan-app/src/main/webui/src/ui/features/project/developer/DeveloperToolbar.tsx b/karavan-app/src/main/webui/src/ui/features/project/developer/DeveloperToolbar.tsx
index a568f60b..054aa3c4 100644
--- a/karavan-app/src/main/webui/src/ui/features/project/developer/DeveloperToolbar.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/project/developer/DeveloperToolbar.tsx
@@ -1,15 +1,6 @@
import React from 'react';
-import {useFileStore, useProjectStore} from "@stores/ProjectStore";
-import {shallow} from "zustand/shallow";
import {ProjectTitle} from "@features/project/ProjectTitle";
import {DesignerToggle} from "@features/project/DesignerToggle";
-import {Button, Content, Popover} from "@patternfly/react-core";
-import {DashboardDevelopmentHook} from "@features/dashboard/development/DashboardDevelopmentHook";
-import {CheckIcon} from "@patternfly/react-icons";
-import {useValidationStore} from "@stores/ValidationStore";
-import {KARAVAN_DOT_EXTENSION} from "@core/contants";
-import {DOCKER_COMPOSE} from "@models/ProjectModels";
-import ExclamationCircleIcon from "@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon";
interface DeveloperToolbarProps {
showDesignerToggle?: boolean
@@ -18,75 +9,9 @@ interface DeveloperToolbarProps {
function DeveloperToolbar({showDesignerToggle, showRunButton}: DeveloperToolbarProps) {
- const [project] = useProjectStore((s) => [s.project], shallow)
- const [file] = useFileStore((s) => [s.file], shallow)
- const {getValidationInfoForFile} = DashboardDevelopmentHook();
- const validation = file ? getValidationInfoForFile(project.projectId, file?.name) : undefined;
- const {validateProjectFile, validations} = useValidationStore();
- const showValidateButton = file?.name?.endsWith(KARAVAN_DOT_EXTENSION.CAMEL_YAML)
- || file?.name?.endsWith(KARAVAN_DOT_EXTENSION.KAMELET_YAML)
- || file?.name?.endsWith(DOCKER_COMPOSE)
-
- const errors = validation?.errors;
- const hasErrors = errors?.length > 0;
-
- const popoverBody = (
- <div style={{display: "flex", flexDirection: "column", justifyContent: "flex-start", alignItems: "stretch", gap: "8px"}}>
- {errors?.map((error, index) => {
- const line = error?.details?.line;
- const type = error?.property ? error?.property : error?.type;
- const title = `Error at line ${line}: ${type}`
- return (
- <div key={index} style={{display: "flex", flexDirection: "column", justifyContent: "flex-start", gap: "3px"}}>
- <Content isVisitedLink style={{fontWeight: 'bold', margin: 0}} component="p">{title}</Content>
- <Content style={{margin: 0}} component="p">{error?.message}</Content>
- </div>
- )
- })}
- </div>
- )
-
- const popover = (
- <Popover
- aria-label="Alert popover"
- alertSeverityVariant={'danger'}
- headerComponent="h1"
- bodyContent={popoverBody}
- appendTo={() => document.body}
- >
- <Button icon={<ExclamationCircleIcon/>}
- isDanger={hasErrors}
- variant={'secondary'}
- onClick={_ => {
- validateProjectFile(file.projectId, file.name);
- }}
- >
- Show Errors
- </Button>
- </Popover>
- )
-
- function getValidationButton() {
- return (
- <div style={{paddingRight: 16, display: "flex", flexDirection: "row", gap: "16px", alignItems: "center"}}>
- <Button icon={<CheckIcon/>}
- isDanger={hasErrors}
- variant={'secondary'}
- onClick={_ => {
- validateProjectFile(file.projectId, file.name);
- }}
- >
- Validate
- </Button>
- {hasErrors && popover}
- </div>
- )
- }
-
return (
<div className="project-files-toolbar">
<ProjectTitle/>
- {showValidateButton && getValidationButton()}
{showDesignerToggle && <DesignerToggle/>}
</div>
)
diff --git a/karavan-app/src/main/webui/src/ui/features/project/developer/YamlEditor.tsx b/karavan-app/src/main/webui/src/ui/features/project/developer/YamlEditor.tsx
index f2f13aa4..e1ece20e 100644
--- a/karavan-app/src/main/webui/src/ui/features/project/developer/YamlEditor.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/project/developer/YamlEditor.tsx
@@ -4,13 +4,11 @@ import {MonacoEditorWrapper} from "@features/project/developer/MonacoEditorWrapp
import {Group, Panel} from "react-resizable-panels";
import type * as monaco from "monaco-editor";
import {configureMonacoYaml} from 'monaco-yaml';
-import {useValidationStore} from "@stores/ValidationStore";
import {useDeveloperStore} from "@stores/DeveloperStore";
import camelYaml from "./schemas/camelYamlDslSimplified.json";
import dockerYaml from "./schemas/compose-spec.json";
import {DOCKER_COMPOSE} from "@models/ProjectModels";
import {KARAVAN_DOT_EXTENSION} from "@core/contants";
-import {useDebounceCallback} from "usehooks-ts";
export interface CodeEditorProps {
projectId?: string;
@@ -23,16 +21,13 @@ export interface CodeEditorProps {
export function YamlEditor(props: CodeEditorProps) {
const {projectId, filename, initialCode, onChange, onLinkOpen} = props;
- const {validateProjectFile} = useValidationStore();
const {setValidation} = useDeveloperStore();
const markerListenerRef = useRef<monaco.IDisposable | null>(null);
- const debouncedValidateProjectFile = useDebounceCallback(validateProjectFile, 3000);
// Cleanup the marker listener on unmount
useEffect(() => {
return () => {
markerListenerRef.current?.dispose();
- debouncedValidateProjectFile.cancel();
};
}, []);
@@ -71,14 +66,6 @@ export function YamlEditor(props: CodeEditorProps) {
// Get all markers currently applied to this file
const currentMarkers = monacoInstance.editor.getModelMarkers({ resource: model.uri });
setValidation(currentMarkers?.length === 0, currentMarkers);
- if (currentMarkers.length === 0) {
- // Frontend is valid: Queue the heavy backend validation
- debouncedValidateProjectFile(projectId, filename);
- } else {
- // Frontend is INVALID: Cancel any pending backend validation immediately
- // This prevents useless server load if they just broke the schema!
- debouncedValidateProjectFile.cancel();
- }
}
});
}
diff --git a/karavan-app/src/main/webui/src/ui/features/project/files/FilesSubTab.tsx b/karavan-app/src/main/webui/src/ui/features/project/files/FilesSubTab.tsx
index d07d0583..9cb796b0 100644
--- a/karavan-app/src/main/webui/src/ui/features/project/files/FilesSubTab.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/project/files/FilesSubTab.tsx
@@ -26,7 +26,6 @@ import {ModalConfirmation} from "@shared/ui/ModalConfirmation";
import {EventBus} from "@features/project/designer/utils/EventBus";
import {useSearchStore} from "@stores/SearchStore";
import {RenameFileModal} from "@features/project/RenameFileModal";
-import {DashboardDevelopmentHook} from "@features/dashboard/development/DashboardDevelopmentHook";
import {FileCopyForEnvModal} from "@features/project/files/FileCopyForEnvModal";
import {CamelUtil} from "@core/api/CamelUtil";
import {download, getIcon, sortFiles} from "@features/project/files/FilesTabUtils";
@@ -55,8 +54,6 @@ export function FilesSubTab(props: FilesSubTabProps) {
const [showRename, setShowRename] = useState<boolean>(false);
const [missingEnvs, setMissingEnvs] = useState<string[]>([]);
- const {getProjectFileValidationIcon} = DashboardDevelopmentHook();
-
const filenames = files.map(f => f.name);
const deletedFilenames: string[] = Object.getOwnPropertyNames(diff)
.map(name => diff[name] === 'DELETED' ? name : '')
@@ -201,7 +198,6 @@ export function FilesSubTab(props: FilesSubTabProps) {
const hasRouteTemplate = CamelUtil.hasRouteTemplateDefinitions(file);
const missEnvs = getMissingEnvs(file.name);
const canBeRenamed = !isInfra && !BUILD_IN_FILES.includes(file.name);
- const validationIcon = getProjectFileValidationIcon(file.projectId, file.name);
const commitTime = commitedFiles?.find(f => f.name === file.name)?.commitTime;
const timeAgo = new TimeAgo('en-US')
return (
@@ -234,7 +230,6 @@ export function FilesSubTab(props: FilesSubTabProps) {
}}>
{prefix[2]}
</Button>
- {validationIcon}
</div>
</Td>
<Td modifier={"fitContent"} style={{textAlign: "right"}}>
diff --git a/karavan-app/src/main/webui/src/ui/features/project/files/FilesToolbar.tsx b/karavan-app/src/main/webui/src/ui/features/project/files/FilesToolbar.tsx
index 9ee409fe..0bc769f6 100644
--- a/karavan-app/src/main/webui/src/ui/features/project/files/FilesToolbar.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/project/files/FilesToolbar.tsx
@@ -31,13 +31,10 @@ import {FileSearchToolbarItem} from "@features/project/FileSearchToolbarItem";
import TimeAgo from "javascript-time-ago";
import {useCommitsStore} from "@stores/CommitsStore";
import {BUILD_IN_PROJECTS} from "@models/ProjectModels";
-import {CheckIcon} from "@patternfly/react-icons";
-import {useValidationStore} from "@stores/ValidationStore";
export function FilesToolbar() {
const {fetchProjectCommits} = useCommitsStore();
- const {validateProject} = useValidationStore();
const [config] = useAppConfigStore((s) => [s.config], shallow);
const [project, isPushing, isPulling] = useProjectStore((s) => [s.project, s.isPushing, s.isPulling], shallow)
const [projectsCommited] = useProjectsStore((s) => [s.projectsCommited], shallow)
@@ -178,10 +175,6 @@ export function FilesToolbar() {
})}
</ToggleGroup>
- function validate() {
- validateProject(project.projectId);
- }
-
function onRefresh() {
if (isCommitsTab) {
fetchProjectCommits(project.projectId);
@@ -197,10 +190,6 @@ export function FilesToolbar() {
<div className="project-files-toolbar">
<ProjectTitle/>
{toggle}
- <Button icon={<CheckIcon/>}
- variant={"link"}
- onClick={() => validate()}
- />
<Button icon={<RefreshIcon/>}
variant={"link"}
onClick={() => onRefresh()}
diff --git a/karavan-app/src/main/webui/src/ui/features/project/project-topology/CustomNode.tsx b/karavan-app/src/main/webui/src/ui/features/project/project-topology/CustomNode.tsx
index 873e1494..4e0286b1 100644
--- a/karavan-app/src/main/webui/src/ui/features/project/project-topology/CustomNode.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/project/project-topology/CustomNode.tsx
@@ -7,12 +7,10 @@ import '@features/project/project-topology/topology.css';
import {RouteDefinition} from "@core/model/CamelDefinition";
import {AutoStartupFalseIcon, ErrorHandlerIcon} from "@features/project/designer/icons/OtherIcons";
import {CustomNodeMetricAttachment} from "@features/project/project-topology/CustomNodeMetricAttachment";
-import {DashboardDevelopmentHook} from "@features/dashboard/development/DashboardDevelopmentHook";
import {runInAction} from "mobx";
import {SvgIcon} from "@shared/icons/SvgIcon";
import {useTopologyHook} from "@features/project/project-topology/useTopologyHook";
import {Category, IntentRequestScaleIn, IntentRequestScaleOut} from "@carbon/icons-react";
-import {GENERATED_FILENAME_PREFIX} from "@models/CatalogModels";
function getIcon(data: any) {
if (['route'].includes(data.icon)) {
@@ -130,7 +128,6 @@ function getAttachments(data: any) {
const CustomNode: React.FC<any & WithContextMenuProps> = observer(({element, onContextMenu, contextMenuOpen, selected, ...rest}) => {
const {selectFile, project} = useTopologyHook(undefined);
- const {getProjectFileValidationIcon} = DashboardDevelopmentHook();
const data = element.getData();
const badge: string = ['API', 'RT', 'TR'].includes(data.badge) ? data.badge : data.badge?.substring(0, 1).toUpperCase();
let colorClass = 'route';
@@ -148,8 +145,6 @@ const CustomNode: React.FC<any & WithContextMenuProps> = observer(({element, onC
}
const disableClass = isDisable(data) ? 'disable-node' : '';
- const labelIcon = data.type === 'route' ? getProjectFileValidationIcon(project.projectId, data.fileName) : undefined;
-
const { x, y } = getDefaultShapeDecoratorCenter("lowerRight" as TopologyQuadrant, element);
const decorator = (
@@ -164,11 +159,6 @@ const CustomNode: React.FC<any & WithContextMenuProps> = observer(({element, onC
);
- const showDecorator = data.type === 'route' && data.fileName?.startsWith(GENERATED_FILENAME_PREFIX);
- const isMasGenerated = data.isMasGenerated;
- const gemsClass = isMasGenerated ? " gems-generated" : "";
- colorClass = showDecorator ? 'gen-route' : colorClass;
-
return (
<g onDoubleClick={event => {
event.stopPropagation();
@@ -176,20 +166,18 @@ const CustomNode: React.FC<any & WithContextMenuProps> = observer(({element, onC
}}>
<DefaultNode
showStatusDecorator
- className={"common-node common-node-" + badge + " topology-color-" + colorClass + " " + disableClass + gemsClass}
+ className={"common-node common-node-" + badge + " topology-color-" + colorClass + " " + disableClass}
scaleLabel={true}
element={element}
onContextMenu={onContextMenu}
contextMenuOpen={contextMenuOpen}
attachments={getAttachments(data)}
hideContextMenuKebab={false}
- labelIcon={labelIcon}
labelIconPadding={1}
label={label}
{...rest}
>
{getIcon(data)}
- {showDecorator && decorator}
</DefaultNode>
</g>
)
diff --git a/karavan-app/src/main/webui/src/ui/features/project/project-topology/TopologyToolbar.tsx b/karavan-app/src/main/webui/src/ui/features/project/project-topology/TopologyToolbar.tsx
index 3c97b1aa..63dc87dc 100644
--- a/karavan-app/src/main/webui/src/ui/features/project/project-topology/TopologyToolbar.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/project/project-topology/TopologyToolbar.tsx
@@ -8,16 +8,13 @@ import {useRouteDesignerHook} from "@features/project/designer/route/useRouteDes
import {APPLICATION_PROPERTIES, DOCKER_COMPOSE, DOCKER_STACK} from "@models/ProjectModels";
import {ProjectTitle} from "@features/project/ProjectTitle";
import {useProjectFunctions} from "@features/project/ProjectContext";
-import {CheckIcon, CogIcon, DockerIcon, EllipsisVIcon} from "@patternfly/react-icons";
+import {CogIcon, DockerIcon, EllipsisVIcon} from "@patternfly/react-icons";
import {AddLarge} from "@carbon/icons-react";
-import {DashboardDevelopmentHook} from "@features/dashboard/development/DashboardDevelopmentHook";
-import {useValidationStore} from "@stores/ValidationStore";
import {KubernetesIcon} from "@features/project/designer/icons/ComponentIcons";
export function TopologyToolbar() {
const [config] = useAppConfigStore((s) => [s.config], shallow);
- const {validateProject} = useValidationStore();
const isDev = config.environment === 'dev';
const {
@@ -30,10 +27,6 @@ export function TopologyToolbar() {
} = useProjectFunctions();
const {openSelector} = useRouteDesignerHook();
- const {getProjectValidationIcon, getProjectValidationStatus} = DashboardDevelopmentHook();
- const validationStatus = getProjectValidationStatus(project.projectId)
- const validationIcon = getProjectValidationIcon(project.projectId)
-
const [isOpen, setIsOpen] = useState(false);
const onToggleClick = () => {
@@ -156,7 +149,6 @@ export function TopologyToolbar() {
<ProjectTitle/>
</div>
{primaryButtons}
- {getButton("Validate", 'secondary', <CheckIcon/>, event => validateProject(project.projectId), validationStatus === false)}
{dropDown}
</div>
)
diff --git a/karavan-app/src/main/webui/src/ui/features/projects/ProjectsTableRow.tsx b/karavan-app/src/main/webui/src/ui/features/projects/ProjectsTableRow.tsx
index 87daae5e..ddeed992 100644
--- a/karavan-app/src/main/webui/src/ui/features/projects/ProjectsTableRow.tsx
+++ b/karavan-app/src/main/webui/src/ui/features/projects/ProjectsTableRow.tsx
@@ -14,7 +14,6 @@ import TimeAgo from 'javascript-time-ago'
import en from 'javascript-time-ago/locale/en'
import {ROUTES} from "@app/navigation/Routes";
import {ProjectStatusLabel} from "@features/projects/ProjectStatusLabel";
-import {DashboardDevelopmentHook} from "@features/dashboard/development/DashboardDevelopmentHook";
import {ComplexityProject} from "@features/projects/ComplexityModels";
import {ProjectZipApi} from "@features/projects/ProjectZipApi";
import {ProjectsTableRowComplexity} from "@features/projects/ProjectsTableRowComplexity";
@@ -37,7 +36,6 @@ interface Props {
function ProjectsTableRow(props: Props) {
const {project, complexity, activeUsers, labels, selectedLabels, onLabelClick, projectCommited} = props;
- const {getProjectValidationIcon} = DashboardDevelopmentHook();
const [deployments] = useStatusesStore((state) => [state.deployments], shallow)
const {containers} = useContainerStatusesStore();
const {config} = useAppConfigStore();
@@ -46,7 +44,6 @@ function ProjectsTableRow(props: Props) {
const timeAgo = new TimeAgo('en-US')
const isBuildIn = BUILD_IN_PROJECTS.includes(project.projectId);
- const validationIcon = getProjectValidationIcon(project.projectId);
function getEnvironments(): string [] {
return config.environments && Array.isArray(config.environments) ? Array.from(config.environments) : [];
@@ -69,7 +66,6 @@ function ProjectsTableRow(props: Props) {
}}>
{project.projectId}
</Button>
- {validationIcon}
</Td>
<Td>
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'start', justifyContent: 'start', gap: '3px'}}>
diff --git a/karavan-app/src/main/webui/src/ui/models/ValidationModels.ts b/karavan-app/src/main/webui/src/ui/models/ValidationModels.ts
deleted file mode 100644
index 81ea9913..00000000
--- a/karavan-app/src/main/webui/src/ui/models/ValidationModels.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export class ProjectValidation {
- projectId: string = '';
- lastValidate: number = 0;
- files: ProjectFileValidation[] = [];
- hasErrors: boolean = false;
-}
-
-export class ProjectFileValidation {
- name: string = '';
- errors: any[] = [];
- hasErrors: boolean = false;
-}
diff --git a/karavan-app/src/main/webui/src/ui/stores/ValidationStore.ts b/karavan-app/src/main/webui/src/ui/stores/ValidationStore.ts
deleted file mode 100644
index 393fbbf0..00000000
--- a/karavan-app/src/main/webui/src/ui/stores/ValidationStore.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import {createWithEqualityFn} from "zustand/traditional";
-import {shallow} from "zustand/shallow";
-import {ProjectValidation} from "@models/ValidationModels";
-import isEqual from "lodash/isEqual";
-import {ValidationApi} from "@api/ValidationApi";
-
-interface ValidationState {
- validations: ProjectValidation[];
- fetchValidations: () => Promise<void>;
- validateProject: (projectId: string) => Promise<void>;
- validateProjectFile: (projectId: string, filename: string) => Promise<void>
-}
-
-export const useValidationStore = createWithEqualityFn<ValidationState>((set, get) => ({
- validations: [],
- fetchValidations: async (): Promise<void> => {
- const currentValidations = get().validations;
- await new Promise<ProjectValidation[]>((resolve) => {
- ValidationApi.getAllProjectValidations(resolve);
- }).then(validations=> {
- if (!isEqual(currentValidations, validations)) {
- set({validations: validations});
- }
- })
- },
- validateProject: async (projectId: string): Promise<void> => {
- ValidationApi.validateProject(projectId, () => {
- setTimeout(() => {
- get().fetchValidations();
- }, 3000);
- });
- },
- validateProjectFile: async (projectId: string, filename: string): Promise<void> => {
- ValidationApi.validateProjectFile(projectId, filename, () => {
- setTimeout(() => {
- get().fetchValidations();
- }, 1000);
- });
- },
-}), shallow)