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 cf741583da96e8325622049583df26dca79f8ec6
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Wed Jun 19 17:32:17 2024 -0400

    Cleanup
---
 .../api/{AuthResource.java => PublicResource.java} |  42 +--------
 .../src/main/webui/src/api/ErrorEventBus.ts        |  25 +++++
 karavan-app/src/main/webui/src/api/KaravanApi.tsx  | 104 +++++++++------------
 .../src/main/webui/src/api/ProjectService.ts       |  26 ++++--
 .../main/webui/src/config/ConfigurationPage.tsx    |   2 +-
 karavan-app/src/main/webui/src/project/devmode.css |  39 ++++++++
 .../src/project/trace/RunnerInfoTraceNode.tsx      |  76 +++++++++++++++
 .../src/main/webui/src/services/ServicesPage.tsx   |   3 +-
 .../src/main/webui/src/shared/error/Error.ts       |  11 ---
 .../main/webui/src/shared/error/ErrorResponse.ts   |  15 ---
 .../src/shared/error/UseResponseErrorHandler.ts    |  43 ---------
 .../src/main/webui/src/templates/TemplatesPage.tsx |   2 +-
 karavan-app/src/main/webui/src/util/StringUtils.ts |  35 ++++++-
 13 files changed, 241 insertions(+), 182 deletions(-)

diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/PublicResource.java
similarity index 59%
rename from 
karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java
rename to 
karavan-app/src/main/java/org/apache/camel/karavan/api/PublicResource.java
index 1561486c..aa503c12 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/PublicResource.java
@@ -23,15 +23,12 @@ import jakarta.ws.rs.core.Response;
 import org.apache.camel.karavan.KaravanStartupLoader;
 import org.apache.camel.karavan.kubernetes.KubernetesStatusService;
 import org.eclipse.microprofile.config.ConfigProvider;
-import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.eclipse.microprofile.health.HealthCheckResponse;
 
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
 import java.util.*;
 
 @Path("/public")
-public class AuthResource {
+public class PublicResource {
 
     @Inject
     KaravanStartupLoader karavanStartupLoader;
@@ -39,43 +36,6 @@ public class AuthResource {
     @Inject
     KubernetesStatusService kubernetesStatusService;
 
-    @ConfigProperty(name = "quarkus.security.users.embedded.realm-name", 
defaultValue = "")
-    Optional<String> realm;
-
-    @ConfigProperty(name = "quarkus.security.users.embedded.users")
-    Optional<Map<String,String>> users;
-
-    public static String getMd5Hash(String input) throws 
NoSuchAlgorithmException {
-        MessageDigest md = MessageDigest.getInstance("MD5");
-        byte[] digest = md.digest(input.getBytes());
-        StringBuilder sb = new StringBuilder();
-        for (byte b : digest) {
-            sb.append(String.format("%02x", b));
-        }
-        return sb.toString();
-    }
-
-    @Path("/auth")
-    @POST
-    @Produces(MediaType.APPLICATION_JSON)
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    public Response authenticateUser(@FormParam("username") String username, 
@FormParam("password") String password) {
-        try {
-            if (users.isPresent() && users.get().containsKey(username)) {
-                var pwdStored = users.get().get(username);
-                var pwdReceived = new 
String(Base64.getDecoder().decode(password));
-                var pwdString = username + ":" + realm.orElse("") + ":" + 
pwdReceived;
-                String pwdToCheck = getMd5Hash(pwdString);
-                if (Objects.equals(pwdToCheck, pwdStored)) {
-                    return Response.ok().build();
-                }
-            }
-            return 
Response.status(Response.Status.FORBIDDEN).entity("Incorrect Username and/or 
Password!").build();
-        } catch (Exception e) {
-            return 
Response.status(Response.Status.FORBIDDEN).entity(e.getMessage()).build();
-        }
-    }
-
     @GET
     @Path("/auth")
     @Produces(MediaType.TEXT_PLAIN)
diff --git a/karavan-app/src/main/webui/src/api/ErrorEventBus.ts 
b/karavan-app/src/main/webui/src/api/ErrorEventBus.ts
new file mode 100644
index 00000000..17df7fb2
--- /dev/null
+++ b/karavan-app/src/main/webui/src/api/ErrorEventBus.ts
@@ -0,0 +1,25 @@
+/*
+ * 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 apiErrors = new Subject<any>();
+
+export const ErrorEventBus = {
+
+    sendApiError: (error: any) =>  apiErrors.next(error),
+    onApiError: () => apiErrors.asObservable(),
+}
diff --git a/karavan-app/src/main/webui/src/api/KaravanApi.tsx 
b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
index 4cf61d0d..0ca8f6c9 100644
--- a/karavan-app/src/main/webui/src/api/KaravanApi.tsx
+++ b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
@@ -29,6 +29,7 @@ import {SsoApi} from "./SsoApi";
 import {v4 as uuidv4} from "uuid";
 import {useAppConfigStore} from "./ProjectStore";
 import {EventBus} from "../designer/utils/EventBus";
+import {ErrorEventBus} from "./ErrorEventBus";
 
 const USER_ID_KEY = 'KARAVAN_USER_ID';
 axios.defaults.headers.common['Accept'] = 'application/json';
@@ -46,9 +47,7 @@ export class KaravanApi {
     }
 
     static getUserId(): string {
-        if (KaravanApi.me?.userName !== undefined) {
-            return KaravanApi.me?.userName;
-        } else {
+        if (KaravanApi.authType === 'public') {
             const userId = localStorage.getItem(USER_ID_KEY);
             if (userId !== null && userId !== undefined) {
                 return userId;
@@ -57,11 +56,12 @@ export class KaravanApi {
                 localStorage.setItem(USER_ID_KEY, newId);
                 return newId;
             }
+        } else {
+            return KaravanApi.me?.userName;
         }
     }
 
     static setAuthType(authType: string) {
-        console.log("SetAuthType", authType)
         KaravanApi.authType = authType;
         switch (authType) {
             case "public": {
@@ -124,30 +124,6 @@ export class KaravanApi {
         });
     }
 
-    static async auth(username: string, password: string, after: (ok: boolean, 
res: any) => void) {
-        instance.post('/public/auth',
-            {username: username, password: 
Buffer.from(password).toString('base64')},
-            {headers: {'content-type': 'application/x-www-form-urlencoded'}})
-            .then(res => {
-                if (res.status === 200) {
-                    KaravanApi.basicToken = Buffer.from(username + ":" + 
password).toString('base64');
-                    KaravanApi.setBasicAuthentication();
-                    KaravanApi.getMe(user => {
-                        after(true, res);
-                        useAppConfigStore.setState({isAuthorized: true})
-                    })
-                } else if (res.status === 401) {
-                    useAppConfigStore.setState({isAuthorized: false})
-                    KaravanApi.basicToken = '';
-                    after(false, res);
-                }
-            }).catch(err => {
-            KaravanApi.basicToken = '';
-            useAppConfigStore.setState({isAuthorized: false})
-            after(false, err);
-        });
-    }
-
     static async getReadiness(after: (readiness: any) => void) {
         axios.get('/public/readiness', {headers: {'Accept': 
'application/json'}})
             .then(res => {
@@ -157,8 +133,7 @@ export class KaravanApi {
                     after(undefined);
                 }
             }).catch(err => {
-            console.log(err.message);
-            after(undefined);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -169,7 +144,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -183,7 +158,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -195,7 +170,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -206,7 +181,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -217,7 +192,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -228,7 +203,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -241,7 +216,7 @@ export class KaravanApi {
                     after(undefined);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -252,7 +227,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -263,7 +238,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -274,7 +249,7 @@ export class KaravanApi {
                     after(res.data.map((p: Partial<Project> | undefined) => 
new Project(p)));
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -333,7 +308,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch((err: any) => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
             EventBus.sendAlert("Error", err.message, "danger")
         });
     }
@@ -345,7 +320,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -356,7 +331,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -367,7 +342,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -429,7 +404,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -440,7 +415,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -514,7 +489,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -525,7 +500,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -536,7 +511,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -547,7 +522,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -567,7 +542,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -578,7 +553,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -630,7 +605,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -641,7 +616,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -652,7 +627,7 @@ export class KaravanApi {
                     after();
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -663,7 +638,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -674,7 +649,7 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -703,7 +678,18 @@ export class KaravanApi {
                     after(res.data);
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
+        });
+    }
+
+    static async getKameletsForProject(projectId: string, after: (yaml: 
string) => void) {
+        instance.get('/ui/kamelet/' + projectId, {headers: {'Accept': 
'text/plain'}})
+            .then(res => {
+                if (res.status === 200) {
+                    after(res.data);
+                }
+            }).catch(err => {
+            ErrorEventBus.sendApiError(err);
         });
     }
 
@@ -714,7 +700,7 @@ export class KaravanApi {
                     after(JSON.stringify(res.data));
                 }
             }).catch(err => {
-            console.log(err);
+            ErrorEventBus.sendApiError(err);
         });
     }
 }
diff --git a/karavan-app/src/main/webui/src/api/ProjectService.ts 
b/karavan-app/src/main/webui/src/api/ProjectService.ts
index f32e12fa..bce8a5fa 100644
--- a/karavan-app/src/main/webui/src/api/ProjectService.ts
+++ b/karavan-app/src/main/webui/src/api/ProjectService.ts
@@ -25,7 +25,7 @@ import {
     useStatusesStore,
     useFileStore, useLogStore,
     useProjectsStore,
-    useProjectStore, useDevModeStore, useAppConfigStore
+    useProjectStore, useDevModeStore
 } from './ProjectStore';
 import {ProjectEventBus} from './ProjectEventBus';
 import {EventBus} from "../designer/utils/EventBus";
@@ -98,7 +98,6 @@ export class ProjectService {
     }
 
     public static pushProject(project: Project, commitMessage: string) {
-        useAppConfigStore.setState({notificationFetcherId: 
Math.random().toString()});
         const params = {
             'projectId': project.projectId,
             'message': commitMessage,
@@ -128,18 +127,28 @@ export class ProjectService {
         });
     }
 
-    public static reloadKamelets() {
-        KaravanApi.getKamelets(yamls => {
-            const kamelets: string[] = [];
-            yamls.split(/\n?---\n?/).map(c => c.trim()).forEach(z => 
kamelets.push(z));
-            KameletApi.saveKamelets(kamelets, true);
-        })
+    static afterKameletsLoad(yamls: string): void {
+        const kamelets: string[] = [];
+        yamls.split(/\n?---\n?/).map(c => c.trim()).forEach(z => 
kamelets.push(z));
+        KameletApi.saveKamelets(kamelets, true);
+    }
 
+    public static reloadKamelets(projectId?: string) {
+        if (projectId) {
+            KaravanApi.getKameletsForProject(projectId, 
ProjectService.afterKameletsLoad);
+            useFilesStore.getState().files
+                ?.filter(f => f.name.endsWith('.kamelet.yaml'))
+                .map(f => f.name.replace('.kamelet.yaml', ''))
+                .forEach(name => KameletApi.saveCustomKameletName(name))
+        } else {
+            KaravanApi.getKamelets(ProjectService.afterKameletsLoad)
+        }
         KaravanApi.getFiles("kamelets", (files: ProjectFile[]) => {
             files.map(f => f.name.replace('.kamelet.yaml', ''))
                 .forEach(name => KameletApi.saveCustomKameletName(name))
         });
     }
+
     public static updateFile(file: ProjectFile, active: boolean) {
         KaravanApi.putProjectFile(file, res => {
             if (res.status === 200) {
@@ -282,6 +291,7 @@ export class ProjectService {
         });
         KaravanApi.getFiles(projectId, (files: ProjectFile[]) => {
             useFilesStore.setState({files: files});
+            ProjectService.reloadKamelets(projectId);
         });
 
         KaravanApi.getFilesDiff(projectId, (diff: any) => {
diff --git a/karavan-app/src/main/webui/src/config/ConfigurationPage.tsx 
b/karavan-app/src/main/webui/src/config/ConfigurationPage.tsx
index 80fd439b..000b1718 100644
--- a/karavan-app/src/main/webui/src/config/ConfigurationPage.tsx
+++ b/karavan-app/src/main/webui/src/config/ConfigurationPage.tsx
@@ -79,7 +79,7 @@ export const ConfigurationPage = (props: Props) => {
             </PageSection>
             <PageSection className="tools-section" padding={{default: 
'noPadding'}}>
                 <Flex direction={{default: "column"}} spaceItems={{default: 
"spaceItemsNone"}}>
-                    <FlexItem className="knowledge-tabs">
+                    <FlexItem>
                         <Tabs activeKey={tab} onSelect={(event, tabIndex) => 
setTab(tabIndex)}>
                             <Tab eventKey="statuses" title="Statuses"/>
                             <Tab eventKey="secrets" title="Secrets" 
isDisabled/>
diff --git a/karavan-app/src/main/webui/src/project/devmode.css 
b/karavan-app/src/main/webui/src/project/devmode.css
new file mode 100644
index 00000000..fea70e8e
--- /dev/null
+++ b/karavan-app/src/main/webui/src/project/devmode.css
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+.karavan .refresher {
+    width: 34px;
+    height: 34px;
+}
+
+.karavan .refresher .spinner {
+    position: absolute;
+    width: 34px;
+    height: 34px;
+}
+
+.karavan .refresher .button {
+    position: absolute;
+    width: 34px;
+    height: 34px;
+    padding: 0;
+    font-size: 16px;
+}
+
+.karavan .refresher .button .pf-v5-c-button__icon {
+    margin: 0;
+}
\ No newline at end of file
diff --git 
a/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceNode.tsx 
b/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceNode.tsx
new file mode 100644
index 00000000..73181663
--- /dev/null
+++ b/karavan-app/src/main/webui/src/project/trace/RunnerInfoTraceNode.tsx
@@ -0,0 +1,76 @@
+/*
+ * 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 React from 'react';
+import {
+    CodeBlock, CodeBlockCode, DataList, DataListCell, DataListItem, 
DataListItemCells, DataListItemRow, DataListWrapModifier,
+    DescriptionList,
+    DescriptionListDescription,
+    DescriptionListGroup,
+    DescriptionListTerm, Panel, PanelHeader, PanelMain, PanelMainBody
+} from '@patternfly/react-core';
+import '../../designer/karavan.css';
+
+interface Props {
+    trace: any
+}
+
+export function RunnerInfoTraceNode (props: Props) {
+
+    const type = props.trace?.message?.body?.type;
+    const body = props.trace?.message?.body?.value;
+    const headers: any[] = [...props.trace?.message?.headers];
+    return (
+        <Panel isScrollable>
+                <PanelMain tabIndex={0}>
+                    <PanelHeader>
+                        <DescriptionList isHorizontal>
+                            <DescriptionListGroup>
+                                
<DescriptionListTerm>Headers</DescriptionListTerm>
+                            </DescriptionListGroup>
+                            <DataList aria-label="Compact data list example" 
isCompact>
+                                {headers.map((header: any, index: number) => (
+                                    <DataListItem key={header[0] + "-" + 
index} aria-labelledby="compact-item1">
+                                        <DataListItemRow>
+                                            <DataListItemCells
+                                                dataListCells={[
+                                                    <DataListCell key="uid" 
>{header.key}</DataListCell>,
+                                                    <DataListCell 
key="type">{header.type}</DataListCell>,
+                                                    <DataListCell 
key="routeId" wrapModifier={DataListWrapModifier.truncate}>
+                                                        {header.value}
+                                                    </DataListCell>,
+                                                ]}
+                                            />
+                                        </DataListItemRow>
+                                    </DataListItem>))}
+                            </DataList>
+                            <DescriptionListGroup>
+                                <DescriptionListTerm>Body</DescriptionListTerm>
+                                <DescriptionListDescription>
+                                    {type}
+                                </DescriptionListDescription>
+                            </DescriptionListGroup>
+                        </DescriptionList>
+                    </PanelHeader>
+                    <PanelMainBody style={{padding: "0"}}>
+                        <CodeBlock title="Body">
+                            <CodeBlockCode 
id="code-content">{body}</CodeBlockCode>
+                        </CodeBlock>
+                    </PanelMainBody>
+                </PanelMain>
+            </Panel>
+    );
+}
diff --git a/karavan-app/src/main/webui/src/services/ServicesPage.tsx 
b/karavan-app/src/main/webui/src/services/ServicesPage.tsx
index 725b2124..252fa667 100644
--- a/karavan-app/src/main/webui/src/services/ServicesPage.tsx
+++ b/karavan-app/src/main/webui/src/services/ServicesPage.tsx
@@ -32,7 +32,6 @@ import {
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
 import RefreshIcon from '@patternfly/react-icons/dist/esm/icons/sync-alt-icon';
-import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon';
 import {
        Td,
        Th,
@@ -143,7 +142,7 @@ export function ServicesPage () {
             <PageSection className="tools-section" padding={{default: 
'noPadding'}}>
                 <MainToolbar title={title()} tools={getTools()}/>
             </PageSection>
-            <PageSection isFilled className="kamelets-page">
+            <PageSection isFilled className="scrolled-page">
                 {getServicesTable()}
             </PageSection>
             <ProjectLogPanel/>
diff --git a/karavan-app/src/main/webui/src/shared/error/Error.ts 
b/karavan-app/src/main/webui/src/shared/error/Error.ts
deleted file mode 100644
index b0e0dac3..00000000
--- a/karavan-app/src/main/webui/src/shared/error/Error.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export class Error {
-    field: string = '';
-    message: string = '';
-    code: string = '';
-
-    constructor(field: string, message: string, code: string) {
-        this.field = field;
-        this.message = message;
-        this.code = code;
-    }
-}
\ No newline at end of file
diff --git a/karavan-app/src/main/webui/src/shared/error/ErrorResponse.ts 
b/karavan-app/src/main/webui/src/shared/error/ErrorResponse.ts
deleted file mode 100644
index 70728e36..00000000
--- a/karavan-app/src/main/webui/src/shared/error/ErrorResponse.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import {Error} from "./Error";
-
-export class ErrorResponse {
-    status: number = 0;
-    error: string = '';
-    message: string = '';
-    errors: Array<Error> = [];
-
-    constructor(status: number, error: string, message: string, errors: 
Array<Error>) {
-        this.status = status;
-        this.error = error;
-        this.message = message;
-        this.errors = errors;
-    }
-}
\ No newline at end of file
diff --git 
a/karavan-app/src/main/webui/src/shared/error/UseResponseErrorHandler.ts 
b/karavan-app/src/main/webui/src/shared/error/UseResponseErrorHandler.ts
deleted file mode 100644
index 7e8c557a..00000000
--- a/karavan-app/src/main/webui/src/shared/error/UseResponseErrorHandler.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import {useState} from 'react';
-import {ErrorResponse} from "./ErrorResponse";
-import {Error} from "./Error";
-import {AxiosError} from "axios";
-
-export function useResponseErrorHandler(errorResponseToFormFields: Map<string, 
string>, setError: any) {
-    const [globalErrors, setGlobalErrors] = useState<string[]>([]);
-
-    function registerResponseErrors(axiosError: AxiosError) {
-        const errorResponse: ErrorResponse = axiosError.response?.data as 
ErrorResponse;
-        // Register field errors if field errors were returned
-        if (errorResponse.errors) {
-            // Reset global error
-            setGlobalErrors([]);
-
-            // Register all field errors
-            errorResponse.errors?.forEach((error: Error) => {
-                // If field name was found in mapping table, register it to 
the form error
-                if (errorResponseToFormFields.get(error.field)) {
-                    setError(errorResponseToFormFields.get(error.field), {
-                        type: 'custom',
-                        message: error.message
-                    });
-                }
-                // If field name was not found in mapping table, register it 
to the global error
-                else {
-                    // Make copy as state shouldn't be mutated
-                    setGlobalErrors(prevGlobalErrors => [...prevGlobalErrors, 
error.message]);
-                }
-            });
-        }
-        // Register global error if no field errors were returned
-        else {
-            setGlobalErrors([errorResponse.message]);
-        }
-    }
-
-    function resetGlobalErrors() {
-        setGlobalErrors([]);
-    }
-
-    return [globalErrors, registerResponseErrors, resetGlobalErrors] as const;
-}
diff --git a/karavan-app/src/main/webui/src/templates/TemplatesPage.tsx 
b/karavan-app/src/main/webui/src/templates/TemplatesPage.tsx
index f13242f1..c63df7b0 100644
--- a/karavan-app/src/main/webui/src/templates/TemplatesPage.tsx
+++ b/karavan-app/src/main/webui/src/templates/TemplatesPage.tsx
@@ -117,7 +117,7 @@ export function TemplatesPage () {
             <PageSection className="tools-section" padding={{default: 
'noPadding'}}>
                 <MainToolbar title={title()} tools={getTools()}/>
             </PageSection>
-            <PageSection isFilled className="kamelets-page">
+            <PageSection isFilled className="scrolled-page">
                 {getProjectsTable()}
             </PageSection>
         </PageSection>
diff --git a/karavan-app/src/main/webui/src/util/StringUtils.ts 
b/karavan-app/src/main/webui/src/util/StringUtils.ts
index ced025d4..ec04e358 100644
--- a/karavan-app/src/main/webui/src/util/StringUtils.ts
+++ b/karavan-app/src/main/webui/src/util/StringUtils.ts
@@ -23,4 +23,37 @@ export function getPathParams(input: string): string[] {
 
 export function getShortCommit(commitId: string): string {
     return commitId ? commitId?.substring(0, 7) : "-";
-}
\ No newline at end of file
+}
+
+export function hasLowercase(password: string): boolean {
+    const pattern = /[a-z]/;
+    return pattern.test(password);
+}
+
+export function hasUppercase(password: string): boolean {
+    const pattern = /[A-Z]/;
+    return pattern.test(password);
+}
+
+export function hasDigit(password: string): boolean {
+    const pattern = /\d/;
+    return pattern.test(password);
+}
+
+export function hasSpecialCharacter(password: string): boolean {
+    const pattern = /[@$!%*?&]/;
+    return pattern.test(password);
+}
+
+export function hasMinimumLength(password: string, minLength: number = 8): 
boolean {
+    return password.length >= minLength;
+}
+
+
+export function isValidPassword(password: string): boolean {
+    return hasLowercase(password) &&
+        hasUppercase(password) &&
+        hasDigit(password) &&
+        hasSpecialCharacter(password) &&
+        hasMinimumLength(password);
+}

Reply via email to