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 2023/08/28 23:57:34 UTC

[camel-karavan] branch main updated: Fix #653

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


The following commit(s) were added to refs/heads/main by this push:
     new 4d79ee8f Fix #653
4d79ee8f is described below

commit 4d79ee8f788e90b0e939279a1538266aef766710
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Mon Aug 28 19:57:22 2023 -0400

    Fix #653
---
 karavan-designer/src/App.tsx                       | 41 ++---------------
 karavan-designer/src/designer/KaravanDesigner.tsx  | 15 +++++--
 karavan-designer/src/designer/utils/EventBus.ts    | 20 +++++++++
 .../src/designer/utils}/Notification.tsx           | 11 ++---
 karavan-space/src/App.tsx                          | 52 ++--------------------
 karavan-space/src/designer/KaravanDesigner.tsx     | 15 +++++--
 karavan-space/src/designer/utils/EventBus.ts       | 20 +++++++++
 .../src/designer/utils}/Notification.tsx           | 11 ++---
 karavan-space/src/space/GithubModal.tsx            | 10 ++---
 karavan-space/src/space/SpaceBus.ts                | 41 -----------------
 karavan-space/src/space/UploadModal.tsx            |  6 +--
 karavan-vscode/src/designerView.ts                 | 18 +++++---
 .../src/main/webui/src/api/ProjectEventBus.ts      |  5 +--
 .../src/main/webui/src/api/ProjectModels.ts        | 13 ------
 .../src/main/webui/src/api/ProjectService.ts       |  9 ++--
 .../main/webui/src/designer/KaravanDesigner.tsx    | 15 +++++--
 .../src/main/webui/src/designer/utils/EventBus.ts  | 20 +++++++++
 .../src/{main => designer/utils}/Notification.tsx  | 11 ++---
 .../karavan-app/src/main/webui/src/main/Main.tsx   |  7 ++-
 .../src/main/webui/src/main/MainLogin.tsx          |  4 +-
 .../webui/src/project/files/UploadFileModal.tsx    |  7 +--
 21 files changed, 145 insertions(+), 206 deletions(-)

diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index 02476d89..0874bb06 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -30,20 +30,8 @@ import './designer/karavan.css';
 import {DesignerPage} from "./DesignerPage";
 import {TemplateApi} from "karavan-core/lib/api/TemplateApi";
 import {KnowledgebasePage} from "./knowledgebase/KnowledgebasePage";
-
-class ToastMessage {
-    id: string = ''
-    text: string = ''
-    title: string = ''
-    variant?: 'success' | 'danger' | 'warning' | 'info' | 'default';
-
-    constructor(title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'default') {
-        this.id = Date.now().toString().concat(Math.random().toString());
-        this.title = title;
-        this.text = text;
-        this.variant = variant;
-    }
-}
+import {Notification} from "./designer/utils/Notification";
+import {EventBus, ToastMessage} from "./designer/utils/EventBus";
 
 class MenuItem {
     pageId: string = '';
@@ -66,29 +54,17 @@ interface State {
     key: string
     loaded?: boolean,
     pageId: string,
-    alerts: ToastMessage[],
 }
 
 class App extends React.Component<Props, State> {
 
     public state: State = {
         pageId: "designer",
-        alerts: [],
         name: 'example.yaml',
         key: '',
         yaml: ''
     }
 
-    toast = (title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'default') => {
-        const mess = [];
-        mess.push(...this.state.alerts, new ToastMessage(title, text, variant));
-        this.setState({alerts: mess})
-    }
-
-    deleteErrorMessage = (id: string) => {
-        this.setState({alerts: this.state.alerts.filter(a => a.id !== id)})
-    }
-
     componentDidMount() {
         Promise.all([
             fetch("kamelets/kamelets.yaml"),
@@ -122,7 +98,7 @@ class App extends React.Component<Props, State> {
                 ComponentApi.setSupportedOnly(true);
             }
         }).catch(err =>
-            this.toast("Error", err.text, 'danger')
+            EventBus.sendAlert("Error", err.text, 'danger')
         );
     }
 
@@ -202,16 +178,7 @@ class App extends React.Component<Props, State> {
         const {loaded} = this.state;
         return (
             <Page className="karavan">
-                <AlertGroup isToast isLiveRegion>
-                    {this.state.alerts.map((e: ToastMessage) => (
-                        // @ts-ignore
-                        <Alert key={e.id} className="main-alert" variant={e.variant} title={e.title}
-                               timeout={e.variant === "success" ? 2000 : 10000}
-                               actionClose={<AlertActionCloseButton onClose={() => this.deleteErrorMessage(e.id)}/>}>
-                            {e.text}
-                        </Alert>
-                    ))}
-                </AlertGroup>
+                <Notification/>
                 <Flex direction={{default: "row"}} style={{width: "100%", height: "100%"}}
                       alignItems={{default: "alignItemsStretch"}} spaceItems={{default: 'spaceItemsNone'}}>
                     <FlexItem>
diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx b/karavan-designer/src/designer/KaravanDesigner.tsx
index b101edd7..ed6ad193 100644
--- a/karavan-designer/src/designer/KaravanDesigner.tsx
+++ b/karavan-designer/src/designer/KaravanDesigner.tsx
@@ -35,7 +35,7 @@ import {useDesignerStore, useIntegrationStore} from "./KaravanStore";
 import {shallow} from "zustand/shallow";
 import {getDesignerIcon} from "./utils/KaravanIcons";
 import {InfrastructureAPI} from "./utils/InfrastructureAPI";
-import {EventBus, IntegrationUpdate} from "./utils/EventBus";
+import {EventBus, IntegrationUpdate, ToastMessage} from "./utils/EventBus";
 import {RestDesigner} from "./rest/RestDesigner";
 import {BeansDesigner} from "./beans/BeansDesigner";
 
@@ -78,11 +78,17 @@ export function KaravanDesigner (props: Props) {
     }, []);
 
     function makeIntegration(yaml: string, filename: string): Integration {
-        if (yaml && CamelDefinitionYaml.yamlIsIntegration(yaml)) {
-            return CamelDefinitionYaml.yamlToIntegration(props.filename, props.yaml)
-        } else {
+        try {
+            if (yaml && CamelDefinitionYaml.yamlIsIntegration(yaml)) {
+                return CamelDefinitionYaml.yamlToIntegration(props.filename, props.yaml)
+            } else {
+                return Integration.createNew(filename, 'plain');
+            }
+        } catch (e) {
+            EventBus.sendAlert("Error parsing YAML", (e as Error).message, 'danger')
             return Integration.createNew(filename, 'plain');
         }
+
     }
 
     function save(integration: Integration, propertyOnly: boolean): void {
@@ -134,6 +140,7 @@ export function KaravanDesigner (props: Props) {
                         onChange={(_, checked) => {
                             setHideLogDSL(checked)
                         }}
+                        aria-label={"Hide Log"}
                         id="hideLogDSL"
                         name="hideLogDSL"
                         className={"hide-log"}
diff --git a/karavan-designer/src/designer/utils/EventBus.ts b/karavan-designer/src/designer/utils/EventBus.ts
index ec11019e..8f3f9712 100644
--- a/karavan-designer/src/designer/utils/EventBus.ts
+++ b/karavan-designer/src/designer/utils/EventBus.ts
@@ -16,6 +16,7 @@
  */
 import {Subject} from 'rxjs';
 import {CamelElement, Integration} from "karavan-core/lib/model/IntegrationDefinition";
+import {v4 as uuidv4} from "uuid";
 
 const positions = new Subject<DslPosition>();
 
@@ -70,6 +71,21 @@ export class IntegrationUpdate {
     }
 }
 
+const alerts = new Subject<ToastMessage>();
+export class ToastMessage {
+    id: string = ''
+    text: string = ''
+    title: string = ''
+    variant?: 'success' | 'danger' | 'warning' | 'info' | 'custom';
+
+    constructor(title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom') {
+        this.id = uuidv4();
+        this.title = title;
+        this.text = text;
+        this.variant = variant;
+    }
+}
+
 export const EventBus = {
     sendPosition: (command: "add" | "delete" | "clean",
                    step: CamelElement,
@@ -86,4 +102,8 @@ export const EventBus = {
 
     sendCommand: (command: string, data?: any) => commands.next(new Command(command, data)),
     onCommand: () => commands.asObservable(),
+
+    sendAlert: (title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom' = 'success') =>
+        alerts.next(new ToastMessage(title, text, variant)),
+    onAlert: () => alerts.asObservable(),
 }
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/Notification.tsx b/karavan-designer/src/designer/utils/Notification.tsx
similarity index 74%
copy from karavan-web/karavan-app/src/main/webui/src/main/Notification.tsx
copy to karavan-designer/src/designer/utils/Notification.tsx
index b28933b3..f3572ff4 100644
--- a/karavan-web/karavan-app/src/main/webui/src/main/Notification.tsx
+++ b/karavan-designer/src/designer/utils/Notification.tsx
@@ -3,30 +3,25 @@ import {
     Alert,
     AlertActionCloseButton, AlertGroup,
 } from '@patternfly/react-core';
-import '../designer/karavan.css';
-import {ToastMessage} from "../api/ProjectModels";
-import {ProjectEventBus} from "../api/ProjectEventBus";
+import '../karavan.css';
+import {EventBus, ToastMessage} from "./EventBus";
 
 export function Notification () {
 
     const [alerts, setAlerts] = useState<ToastMessage[]>([]);
 
     useEffect(() => {
-        console.log("Notification Start");
-        const sub = ProjectEventBus.onAlert()?.subscribe((result: ToastMessage) => {
-            console.log(result);
+        const sub = EventBus.onAlert()?.subscribe((result: ToastMessage) => {
             setAlerts(prevState => {
                 return [...prevState, result];
             });
         });
         return () => {
-            console.log("end");
             sub?.unsubscribe();
         };
     }, []);
 
     useEffect(() => {
-        console.log("Notification alert");
     }, [alerts]);
 
     return (
diff --git a/karavan-space/src/App.tsx b/karavan-space/src/App.tsx
index f647aa14..c5d11f87 100644
--- a/karavan-space/src/App.tsx
+++ b/karavan-space/src/App.tsx
@@ -16,8 +16,6 @@
  */
 import * as React from "react";
 import {
-    Alert,
-    AlertActionCloseButton, AlertGroup,
     Bullseye, Button, Divider, Flex, FlexItem,
     Page, Spinner, Tooltip,
 } from "@patternfly/react-core";
@@ -29,24 +27,10 @@ import {KaravanIcon} from "./designer/utils/KaravanIcons";
 import './designer/karavan.css';
 import {SpacePage} from "./space/SpacePage";
 import {GithubModal} from "./space/GithubModal";
-import {Subscription} from "rxjs";
-import {AlertMessage, SpaceBus} from "./space/SpaceBus";
 import {TemplateApi} from "karavan-core/lib/api/TemplateApi";
 import {KnowledgebasePage} from "./knowledgebase/KnowledgebasePage";
-
-class ToastMessage {
-    id: string = ''
-    text: string = ''
-    title: string = ''
-    variant?: 'success' | 'danger' | 'warning' | 'info' | 'custom';
-
-    constructor(title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom') {
-        this.id = Date.now().toString().concat(Math.random().toString());
-        this.title = title;
-        this.text = text;
-        this.variant = variant;
-    }
-}
+import {EventBus, ToastMessage} from "./designer/utils/EventBus";
+import {Notification} from "./designer/utils/Notification";
 
 class MenuItem {
     pageId: string = '';
@@ -70,34 +54,19 @@ interface State {
     loaded?: boolean,
     githubModalIsOpen: boolean,
     pageId: string,
-    alerts: ToastMessage[],
-    sub?: Subscription
 }
 
 class App extends React.Component<Props, State> {
 
     public state: State = {
         pageId: "designer",
-        alerts: [],
         name: 'example.yaml',
         key: '',
         yaml: '',
         githubModalIsOpen: false
     }
 
-    toast = (title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom') => {
-        const mess = [];
-        mess.push(...this.state.alerts, new ToastMessage(title, text, variant));
-        this.setState({alerts: mess})
-    }
-
-    deleteErrorMessage = (id: string) => {
-        this.setState({alerts: this.state.alerts.filter(a => a.id !== id)})
-    }
-
     componentDidMount() {
-        const sub = SpaceBus.onAlert()?.subscribe((evt: AlertMessage) => this.toast(evt.title, evt.message, evt.variant));
-        this.setState({sub: sub});
         Promise.all([
             fetch("kamelets/kamelets.yaml"),
             fetch("components/components.json"),
@@ -120,14 +89,10 @@ class App extends React.Component<Props, State> {
             TemplateApi.saveTemplate("org.apache.camel.AggregationStrategy", data[2]);
             TemplateApi.saveTemplate("org.apache.camel.Processor", data[3]);
         }).catch(err =>
-            this.toast("Error", err.text, 'danger')
+            EventBus.sendAlert("Error", err.text, 'danger')
         );
     }
 
-    componentWillUnmount() {
-        this.state.sub?.unsubscribe();
-    }
-
     save(filename: string, yaml: string, propertyOnly: boolean) {
         this.setState({name: filename, yaml: yaml});
         // console.log(yaml);
@@ -203,16 +168,7 @@ class App extends React.Component<Props, State> {
         const {loaded, githubModalIsOpen, yaml, name} = this.state;
         return (
             <Page className="karavan">
-                <AlertGroup isToast isLiveRegion>
-                    {this.state.alerts.map((e: ToastMessage) => (
-                        <Alert key={e.id} className="main-alert" variant={e.variant} title={e.title}
-                               timeout={e.variant === "success" ? 1000 : 5000}
-                               onTimeout={() => this.deleteErrorMessage(e.id)}
-                               actionClose={<AlertActionCloseButton onClose={() => this.deleteErrorMessage(e.id)}/>}>
-                            {e.text}
-                        </Alert>
-                    ))}
-                </AlertGroup>
+                <Notification/>
                 <>
                     <Flex direction={{default: "row"}} style={{width: "100%", height: "100%"}}
                           alignItems={{default: "alignItemsStretch"}} spaceItems={{default: 'spaceItemsNone'}}>
diff --git a/karavan-space/src/designer/KaravanDesigner.tsx b/karavan-space/src/designer/KaravanDesigner.tsx
index b101edd7..ed6ad193 100644
--- a/karavan-space/src/designer/KaravanDesigner.tsx
+++ b/karavan-space/src/designer/KaravanDesigner.tsx
@@ -35,7 +35,7 @@ import {useDesignerStore, useIntegrationStore} from "./KaravanStore";
 import {shallow} from "zustand/shallow";
 import {getDesignerIcon} from "./utils/KaravanIcons";
 import {InfrastructureAPI} from "./utils/InfrastructureAPI";
-import {EventBus, IntegrationUpdate} from "./utils/EventBus";
+import {EventBus, IntegrationUpdate, ToastMessage} from "./utils/EventBus";
 import {RestDesigner} from "./rest/RestDesigner";
 import {BeansDesigner} from "./beans/BeansDesigner";
 
@@ -78,11 +78,17 @@ export function KaravanDesigner (props: Props) {
     }, []);
 
     function makeIntegration(yaml: string, filename: string): Integration {
-        if (yaml && CamelDefinitionYaml.yamlIsIntegration(yaml)) {
-            return CamelDefinitionYaml.yamlToIntegration(props.filename, props.yaml)
-        } else {
+        try {
+            if (yaml && CamelDefinitionYaml.yamlIsIntegration(yaml)) {
+                return CamelDefinitionYaml.yamlToIntegration(props.filename, props.yaml)
+            } else {
+                return Integration.createNew(filename, 'plain');
+            }
+        } catch (e) {
+            EventBus.sendAlert("Error parsing YAML", (e as Error).message, 'danger')
             return Integration.createNew(filename, 'plain');
         }
+
     }
 
     function save(integration: Integration, propertyOnly: boolean): void {
@@ -134,6 +140,7 @@ export function KaravanDesigner (props: Props) {
                         onChange={(_, checked) => {
                             setHideLogDSL(checked)
                         }}
+                        aria-label={"Hide Log"}
                         id="hideLogDSL"
                         name="hideLogDSL"
                         className={"hide-log"}
diff --git a/karavan-space/src/designer/utils/EventBus.ts b/karavan-space/src/designer/utils/EventBus.ts
index ec11019e..8f3f9712 100644
--- a/karavan-space/src/designer/utils/EventBus.ts
+++ b/karavan-space/src/designer/utils/EventBus.ts
@@ -16,6 +16,7 @@
  */
 import {Subject} from 'rxjs';
 import {CamelElement, Integration} from "karavan-core/lib/model/IntegrationDefinition";
+import {v4 as uuidv4} from "uuid";
 
 const positions = new Subject<DslPosition>();
 
@@ -70,6 +71,21 @@ export class IntegrationUpdate {
     }
 }
 
+const alerts = new Subject<ToastMessage>();
+export class ToastMessage {
+    id: string = ''
+    text: string = ''
+    title: string = ''
+    variant?: 'success' | 'danger' | 'warning' | 'info' | 'custom';
+
+    constructor(title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom') {
+        this.id = uuidv4();
+        this.title = title;
+        this.text = text;
+        this.variant = variant;
+    }
+}
+
 export const EventBus = {
     sendPosition: (command: "add" | "delete" | "clean",
                    step: CamelElement,
@@ -86,4 +102,8 @@ export const EventBus = {
 
     sendCommand: (command: string, data?: any) => commands.next(new Command(command, data)),
     onCommand: () => commands.asObservable(),
+
+    sendAlert: (title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom' = 'success') =>
+        alerts.next(new ToastMessage(title, text, variant)),
+    onAlert: () => alerts.asObservable(),
 }
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/Notification.tsx b/karavan-space/src/designer/utils/Notification.tsx
similarity index 74%
copy from karavan-web/karavan-app/src/main/webui/src/main/Notification.tsx
copy to karavan-space/src/designer/utils/Notification.tsx
index b28933b3..f3572ff4 100644
--- a/karavan-web/karavan-app/src/main/webui/src/main/Notification.tsx
+++ b/karavan-space/src/designer/utils/Notification.tsx
@@ -3,30 +3,25 @@ import {
     Alert,
     AlertActionCloseButton, AlertGroup,
 } from '@patternfly/react-core';
-import '../designer/karavan.css';
-import {ToastMessage} from "../api/ProjectModels";
-import {ProjectEventBus} from "../api/ProjectEventBus";
+import '../karavan.css';
+import {EventBus, ToastMessage} from "./EventBus";
 
 export function Notification () {
 
     const [alerts, setAlerts] = useState<ToastMessage[]>([]);
 
     useEffect(() => {
-        console.log("Notification Start");
-        const sub = ProjectEventBus.onAlert()?.subscribe((result: ToastMessage) => {
-            console.log(result);
+        const sub = EventBus.onAlert()?.subscribe((result: ToastMessage) => {
             setAlerts(prevState => {
                 return [...prevState, result];
             });
         });
         return () => {
-            console.log("end");
             sub?.unsubscribe();
         };
     }, []);
 
     useEffect(() => {
-        console.log("Notification alert");
     }, [alerts]);
 
     return (
diff --git a/karavan-space/src/space/GithubModal.tsx b/karavan-space/src/space/GithubModal.tsx
index 70682d81..87d0ff9b 100644
--- a/karavan-space/src/space/GithubModal.tsx
+++ b/karavan-space/src/space/GithubModal.tsx
@@ -11,7 +11,7 @@ import '../designer/karavan.css';
 import {GithubApi, GithubParams} from "../api/GithubApi";
 import GithubImageIcon from "@patternfly/react-icons/dist/esm/icons/github-icon";
 import {StorageApi} from "../api/StorageApi";
-import {SpaceBus} from "./SpaceBus";
+import {EventBus} from "../designer/utils/EventBus";
 
 interface Props {
     yaml: string,
@@ -76,7 +76,7 @@ export class GithubModal extends React.Component<Props, State> {
                 }
             },
             reason => {
-                SpaceBus.sendAlert('Error', reason.toString(), 'danger');
+                EventBus.sendAlert('Error', reason.toString(), 'danger');
             });
     }
 
@@ -92,7 +92,7 @@ export class GithubModal extends React.Component<Props, State> {
             const email: string = (Array.isArray(data[1]) ? Array.from(data[1]).filter(d => d.primary === true)?.at(0)?.email : '') || '';
             this.setState({token: token, name: name, email:email, owner: login})
         }).catch(err =>
-            SpaceBus.sendAlert('Error', err.toString(), 'danger')
+            EventBus.sendAlert('Error', err.toString(), 'danger')
         );
     }
 
@@ -121,11 +121,11 @@ export class GithubModal extends React.Component<Props, State> {
                 token, this.props.yaml,
                 result => {
                     this.setState({pushing: false});
-                    SpaceBus.sendAlert('Success', "Saved");
+                    EventBus.sendAlert('Success', "Saved");
                     this.props.onClose?.call(this)
                 },
                 reason => {
-                    SpaceBus.sendAlert('Error', reason.toString(), 'danger');
+                    EventBus.sendAlert('Error', reason.toString(), 'danger');
                     this.setState({pushing: false});
                 }
             )
diff --git a/karavan-space/src/space/SpaceBus.ts b/karavan-space/src/space/SpaceBus.ts
deleted file mode 100644
index bb209bfb..00000000
--- a/karavan-space/src/space/SpaceBus.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 {Subject} from 'rxjs';
-
-const alerts = new Subject<AlertMessage>();
-
-export class AlertMessage {
-    title: string;
-    message: string;
-    variant: 'success' | 'danger' | 'warning' | 'info' | 'custom';
-
-
-    constructor(title: string, message: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom') {
-        this.title = title;
-        this.message = message;
-        this.variant = variant;
-    }
-}
-
-export const SpaceBus = {
-    sendAlert: (
-        title: string,
-        message: string,
-        variant: 'success' | 'danger' | 'warning' | 'info' | 'custom' = 'success'
-    ) => alerts.next(new AlertMessage(title, message, variant)),
-    onAlert: () => alerts.asObservable(),
-}
diff --git a/karavan-space/src/space/UploadModal.tsx b/karavan-space/src/space/UploadModal.tsx
index 5db50419..459970c5 100644
--- a/karavan-space/src/space/UploadModal.tsx
+++ b/karavan-space/src/space/UploadModal.tsx
@@ -4,8 +4,8 @@ import {
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
 import {GeneratorApi} from "../api/GeneratorApi";
-import {SpaceBus} from "./SpaceBus";
 import {DropEvent, FileRejection} from "react-dropzone";
+import {EventBus} from "../designer/utils/EventBus";
 
 interface Props {
     isOpen: boolean,
@@ -42,11 +42,11 @@ export class UploadModal extends React.Component<Props, State> {
         this.setState({generating: true});
         const {filename, data} = this.state;
         GeneratorApi.generate(filename, data).then(value => {
-            SpaceBus.sendAlert('Success', 'Generated REST DSL');
+            EventBus.sendAlert('Success', 'Generated REST DSL');
             this.setState({generating: false});
             this.closeModal(value);
         }).catch(reason => {
-            SpaceBus.sendAlert('Error', reason.toString(), 'danger');
+            EventBus.sendAlert('Error', reason.toString(), 'danger');
             this.setState({generating: false});
         })
     }
diff --git a/karavan-vscode/src/designerView.ts b/karavan-vscode/src/designerView.ts
index 7d9a2c31..5caa9beb 100644
--- a/karavan-vscode/src/designerView.ts
+++ b/karavan-vscode/src/designerView.ts
@@ -32,15 +32,21 @@ export class DesignerView {
     }
     karavanOpen(fullPath: string, tab?: string) {
         utils.readFile(path.resolve(fullPath)).then(readData => {
+            
             const yaml = Buffer.from(readData).toString('utf8');
             const filename = path.basename(fullPath);
             const relativePath = utils.getRalativePath(fullPath);
-            const integration = utils.parceYaml(filename, yaml);
-
-            if (integration[0]) {
-                this.openKaravanWebView(filename, relativePath, fullPath, integration[1], tab);
-            } else {
-                window.showErrorMessage("File is not Camel Integration!")
+            let integration;
+            try {
+                integration = utils.parceYaml(filename, yaml);
+            } catch (e) {
+                window.showErrorMessage("Error parcing YAML!")
+            } finally {
+                if (integration && integration[0]) {
+                    this.openKaravanWebView(filename, relativePath, fullPath, integration[1], tab);
+                } else {
+                    window.showErrorMessage("File is not Camel Integration!")
+                }
             }
         })
     }
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectEventBus.ts b/karavan-web/karavan-app/src/main/webui/src/api/ProjectEventBus.ts
index 53658da9..2c8f98ce 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectEventBus.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectEventBus.ts
@@ -15,13 +15,12 @@
  * limitations under the License.
  */
 import {BehaviorSubject, Subject} from 'rxjs';
-import {Project, ToastMessage} from "./ProjectModels";
+import {Project} from "./ProjectModels";
 
 const selectedProject = new BehaviorSubject<Project | undefined>(undefined);
 const currentFile = new BehaviorSubject<string | undefined>(undefined);
 const mode = new BehaviorSubject<"design" | "code">("design");
 const log = new Subject<["add" | "set", string]>();
-const alerts = new Subject<ToastMessage>();
 
 export class ShowLogCommand {
     type: 'container' | 'pipeline'
@@ -57,6 +56,4 @@ export const ProjectEventBus = {
     sendLog: (type: "add" | "set", m: string) =>  log.next([type, m]),
     onLog: () => log.asObservable(),
 
-    sendAlert: (alert: ToastMessage) =>  alerts.next(alert),
-    onAlert: () => alerts.asObservable(),
 }
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts b/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts
index d8056c37..ce19158a 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts
@@ -151,16 +151,3 @@ export function getProjectFileType (file: ProjectFile) {
     return ProjectFileTypes.filter(p => p.extension === extension).map(p => p.title)[0];
 }
 
-export class ToastMessage {
-    id: string = ''
-    text: string = ''
-    title: string = ''
-    variant?: 'success' | 'danger' | 'warning' | 'info' | 'custom';
-
-    constructor(title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom') {
-        this.id = uuidv4();
-        this.title = title;
-        this.text = text;
-        this.variant = variant;
-    }
-}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
index 487669d2..9ebc6eda 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
@@ -1,5 +1,5 @@
 import {KaravanApi} from './KaravanApi';
-import {DeploymentStatus, ContainerStatus, Project, ProjectFile, ToastMessage} from './ProjectModels';
+import {DeploymentStatus, ContainerStatus, Project, ProjectFile} from './ProjectModels';
 import {TemplateApi} from 'karavan-core/lib/api/TemplateApi';
 import {InfrastructureAPI} from '../designer/utils/InfrastructureAPI';
 import {unstable_batchedUpdates} from 'react-dom'
@@ -11,6 +11,7 @@ import {
     useProjectStore, useDevModeStore
 } from './ProjectStore';
 import {ProjectEventBus} from './ProjectEventBus';
+import {EventBus} from "../designer/utils/EventBus";
 
 export class ProjectService {
 
@@ -47,7 +48,7 @@ export class ProjectService {
             if (res.status === 200) {
                 useLogStore.setState({showLog: false, type: 'container'})
             } else {
-                ProjectEventBus.sendAlert(new ToastMessage('Error stopping DevMode container', res.statusText, 'warning'))
+                EventBus.sendAlert('Error stopping DevMode container', res.statusText, 'warning')
             }
         });
     }
@@ -59,7 +60,7 @@ export class ProjectService {
             if (res.status === 200) {
                 useLogStore.setState({showLog: false, type: 'container'})
             } else {
-                ProjectEventBus.sendAlert(new ToastMessage('Error stopping DevMode container', res.statusText, 'warning'))
+                EventBus.sendAlert('Error stopping DevMode container', res.statusText, 'warning')
             }
         });
     }
@@ -72,7 +73,7 @@ export class ProjectService {
             if (res.status === 202) {
                 useLogStore.setState({showLog: false, type: 'container'})
             } else {
-                ProjectEventBus.sendAlert(new ToastMessage('Error delete runner', res.statusText, 'warning'))
+                EventBus.sendAlert('Error delete runner', res.statusText, 'warning')
             }
         });
     }
diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx b/karavan-web/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx
index b101edd7..ed6ad193 100644
--- a/karavan-web/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx
@@ -35,7 +35,7 @@ import {useDesignerStore, useIntegrationStore} from "./KaravanStore";
 import {shallow} from "zustand/shallow";
 import {getDesignerIcon} from "./utils/KaravanIcons";
 import {InfrastructureAPI} from "./utils/InfrastructureAPI";
-import {EventBus, IntegrationUpdate} from "./utils/EventBus";
+import {EventBus, IntegrationUpdate, ToastMessage} from "./utils/EventBus";
 import {RestDesigner} from "./rest/RestDesigner";
 import {BeansDesigner} from "./beans/BeansDesigner";
 
@@ -78,11 +78,17 @@ export function KaravanDesigner (props: Props) {
     }, []);
 
     function makeIntegration(yaml: string, filename: string): Integration {
-        if (yaml && CamelDefinitionYaml.yamlIsIntegration(yaml)) {
-            return CamelDefinitionYaml.yamlToIntegration(props.filename, props.yaml)
-        } else {
+        try {
+            if (yaml && CamelDefinitionYaml.yamlIsIntegration(yaml)) {
+                return CamelDefinitionYaml.yamlToIntegration(props.filename, props.yaml)
+            } else {
+                return Integration.createNew(filename, 'plain');
+            }
+        } catch (e) {
+            EventBus.sendAlert("Error parsing YAML", (e as Error).message, 'danger')
             return Integration.createNew(filename, 'plain');
         }
+
     }
 
     function save(integration: Integration, propertyOnly: boolean): void {
@@ -134,6 +140,7 @@ export function KaravanDesigner (props: Props) {
                         onChange={(_, checked) => {
                             setHideLogDSL(checked)
                         }}
+                        aria-label={"Hide Log"}
                         id="hideLogDSL"
                         name="hideLogDSL"
                         className={"hide-log"}
diff --git a/karavan-web/karavan-app/src/main/webui/src/designer/utils/EventBus.ts b/karavan-web/karavan-app/src/main/webui/src/designer/utils/EventBus.ts
index ec11019e..8f3f9712 100644
--- a/karavan-web/karavan-app/src/main/webui/src/designer/utils/EventBus.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/designer/utils/EventBus.ts
@@ -16,6 +16,7 @@
  */
 import {Subject} from 'rxjs';
 import {CamelElement, Integration} from "karavan-core/lib/model/IntegrationDefinition";
+import {v4 as uuidv4} from "uuid";
 
 const positions = new Subject<DslPosition>();
 
@@ -70,6 +71,21 @@ export class IntegrationUpdate {
     }
 }
 
+const alerts = new Subject<ToastMessage>();
+export class ToastMessage {
+    id: string = ''
+    text: string = ''
+    title: string = ''
+    variant?: 'success' | 'danger' | 'warning' | 'info' | 'custom';
+
+    constructor(title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom') {
+        this.id = uuidv4();
+        this.title = title;
+        this.text = text;
+        this.variant = variant;
+    }
+}
+
 export const EventBus = {
     sendPosition: (command: "add" | "delete" | "clean",
                    step: CamelElement,
@@ -86,4 +102,8 @@ export const EventBus = {
 
     sendCommand: (command: string, data?: any) => commands.next(new Command(command, data)),
     onCommand: () => commands.asObservable(),
+
+    sendAlert: (title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom' = 'success') =>
+        alerts.next(new ToastMessage(title, text, variant)),
+    onAlert: () => alerts.asObservable(),
 }
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/Notification.tsx b/karavan-web/karavan-app/src/main/webui/src/designer/utils/Notification.tsx
similarity index 74%
rename from karavan-web/karavan-app/src/main/webui/src/main/Notification.tsx
rename to karavan-web/karavan-app/src/main/webui/src/designer/utils/Notification.tsx
index b28933b3..f3572ff4 100644
--- a/karavan-web/karavan-app/src/main/webui/src/main/Notification.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/designer/utils/Notification.tsx
@@ -3,30 +3,25 @@ import {
     Alert,
     AlertActionCloseButton, AlertGroup,
 } from '@patternfly/react-core';
-import '../designer/karavan.css';
-import {ToastMessage} from "../api/ProjectModels";
-import {ProjectEventBus} from "../api/ProjectEventBus";
+import '../karavan.css';
+import {EventBus, ToastMessage} from "./EventBus";
 
 export function Notification () {
 
     const [alerts, setAlerts] = useState<ToastMessage[]>([]);
 
     useEffect(() => {
-        console.log("Notification Start");
-        const sub = ProjectEventBus.onAlert()?.subscribe((result: ToastMessage) => {
-            console.log(result);
+        const sub = EventBus.onAlert()?.subscribe((result: ToastMessage) => {
             setAlerts(prevState => {
                 return [...prevState, result];
             });
         });
         return () => {
-            console.log("end");
             sub?.unsubscribe();
         };
     }, []);
 
     useEffect(() => {
-        console.log("Notification alert");
     }, [alerts]);
 
     return (
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/Main.tsx b/karavan-web/karavan-app/src/main/webui/src/main/Main.tsx
index 2ccd2264..75ec85ec 100644
--- a/karavan-web/karavan-app/src/main/webui/src/main/Main.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/main/Main.tsx
@@ -10,16 +10,15 @@ import {ProjectPage} from "../project/ProjectPage";
 import {ServicesPage} from "../services/ServicesPage";
 import {ContainersPage} from "../containers/ContainersPage";
 import {KnowledgebasePage} from "../knowledgebase/KnowledgebasePage";
-import {ProjectEventBus} from "../api/ProjectEventBus";
-import {ToastMessage} from "../api/ProjectModels";
 import {SsoApi} from "../api/SsoApi";
 import {useAppConfigStore} from "../api/ProjectStore";
 import {shallow} from "zustand/shallow";
 import {PageNavigation} from "./PageNavigation";
-import {Notification} from "./Notification";
 import {useMainHook} from "./useMainHook";
 import {MainDataPoller} from "./MainDataPoller";
 import {TemplatesPage} from "../templates/TemplatesPage";
+import {EventBus} from "../designer/utils/EventBus";
+import {Notification} from "../designer/utils/Notification";
 
 export function Main () {
 
@@ -55,7 +54,7 @@ export function Main () {
 
 
     function toast(title: string, text: string, variant: 'success' | 'danger' | 'warning' | 'info' | 'custom') {
-        ProjectEventBus.sendAlert(new ToastMessage(title, text, variant))
+        EventBus.sendAlert(title, text, variant)
     }
 
     return (
diff --git a/karavan-web/karavan-app/src/main/webui/src/main/MainLogin.tsx b/karavan-web/karavan-app/src/main/webui/src/main/MainLogin.tsx
index 33e04e88..1d097e48 100644
--- a/karavan-web/karavan-app/src/main/webui/src/main/MainLogin.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/main/MainLogin.tsx
@@ -6,7 +6,7 @@ import {KaravanApi} from "../api/KaravanApi";
 import {useAppConfigStore} from "../api/ProjectStore";
 import {shallow} from "zustand/shallow";
 import {ProjectEventBus} from "../api/ProjectEventBus";
-import {ToastMessage} from "../api/ProjectModels";
+import {EventBus} from "../designer/utils/EventBus";
 
 export function MainLogin () {
 
@@ -28,7 +28,7 @@ export function MainLogin () {
         KaravanApi.auth(username, password, (res: any) => {
             if (res?.status === 200) {
             } else {
-                ProjectEventBus.sendAlert(new ToastMessage("Error", "Incorrect username and/or password!", "danger"))
+                EventBus.sendAlert("Error", "Incorrect username and/or password!", "danger")
             }
         });
     }
diff --git a/karavan-web/karavan-app/src/main/webui/src/project/files/UploadFileModal.tsx b/karavan-web/karavan-app/src/main/webui/src/project/files/UploadFileModal.tsx
index 8ab84346..39620879 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/files/UploadFileModal.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/files/UploadFileModal.tsx
@@ -20,11 +20,12 @@ import {
     Button, Modal, FormGroup, ModalVariant, Switch, Form, FileUpload, Radio
 } from '@patternfly/react-core';
 import '../../designer/karavan.css';
-import {ProjectFile, ToastMessage} from "../../api/ProjectModels";
+import {ProjectFile} from "../../api/ProjectModels";
 import {KaravanApi} from "../../api/KaravanApi";
 import {useFileStore} from "../../api/ProjectStore";
 import {ProjectEventBus} from "../../api/ProjectEventBus";
 import {Accept, DropEvent, FileRejection} from "react-dropzone";
+import {EventBus} from "../../designer/utils/EventBus";
 
 interface Props {
     projectId: string,
@@ -69,7 +70,7 @@ export class UploadFileModal extends React.Component<Props, State> {
                     this.closeModal();
                 } else {
                     this.closeModal();
-                    ProjectEventBus.sendAlert(new ToastMessage("Error", res.statusText, "warning"))
+                    EventBus.sendAlert("Error", res.statusText, "warning")
                 }
             })
         } else {
@@ -79,7 +80,7 @@ export class UploadFileModal extends React.Component<Props, State> {
                     this.closeModal();
                 } else {
                     this.closeModal();
-                    ProjectEventBus.sendAlert(new ToastMessage("Error", res.statusText, "warning"))
+                    EventBus.sendAlert("Error", res.statusText, "warning")
                 }
             })
         }