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 2024/04/02 00:23:40 UTC
(camel-karavan) branch main updated (c003b70a -> c4028cb5)
This is an automated email from the ASF dual-hosted git repository.
marat pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
from c003b70a Paths redesign
new 4c48d656 Improvements
new c4028cb5 Improvements
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../org/apache/camel/karavan/code/CodeService.java | 46 +++++++-
.../webui/src/util/ModalDeleteConfirmation.tsx | 35 ++++++
karavan-app/src/main/webui/src/util/form-util.css | 12 ++
.../src/main/webui/src/util/useFormUtil.tsx | 130 +++++++++++++++++++++
karavan-core/src/core/api/TopologyUtils.ts | 2 +-
5 files changed, 223 insertions(+), 2 deletions(-)
create mode 100644 karavan-app/src/main/webui/src/util/ModalDeleteConfirmation.tsx
create mode 100644 karavan-app/src/main/webui/src/util/form-util.css
create mode 100644 karavan-app/src/main/webui/src/util/useFormUtil.tsx
(camel-karavan) 02/02: Improvements
Posted by ma...@apache.org.
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 c4028cb5b662ec12ddd8289f68204d245f8f153c
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Mon Apr 1 20:23:29 2024 -0400
Improvements
---
karavan-core/src/core/api/TopologyUtils.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/karavan-core/src/core/api/TopologyUtils.ts b/karavan-core/src/core/api/TopologyUtils.ts
index 73821493..db76667e 100644
--- a/karavan-core/src/core/api/TopologyUtils.ts
+++ b/karavan-core/src/core/api/TopologyUtils.ts
@@ -150,9 +150,9 @@ export class TopologyUtils {
const result:TopologyRestNode[] = [];
integration.forEach(i => {
const filename = i.metadata.name;
- const uris: string[] = [];
const routes = i.spec.flows?.filter(flow => flow.dslName === 'RestDefinition');
routes?.forEach((rest: RestDefinition) => {
+ const uris: string[] = [];
rest?.get?.forEach((d: GetDefinition) => {
if (d.to) uris.push(d.to);
});
(camel-karavan) 01/02: Improvements
Posted by ma...@apache.org.
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 4c48d656c082abc94d1edb8c2c812b28b4dca9a8
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Mon Apr 1 20:23:24 2024 -0400
Improvements
---
.../org/apache/camel/karavan/code/CodeService.java | 46 +++++++-
.../webui/src/util/ModalDeleteConfirmation.tsx | 35 ++++++
karavan-app/src/main/webui/src/util/form-util.css | 12 ++
.../src/main/webui/src/util/useFormUtil.tsx | 130 +++++++++++++++++++++
4 files changed, 222 insertions(+), 1 deletion(-)
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java b/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
index 03a646d6..b4290c01 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
@@ -48,6 +48,13 @@ import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import java.io.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
@@ -169,7 +176,7 @@ public class CodeService {
public String getTemplateText(String fileName) {
try {
List<ProjectFile> files = karavanCacheService.getProjectFiles(Project.Type.templates.name());
- // replaceAll("\r\n", "\n")) has been add to eliminate the impact of editing the template files from windows machine.
+ // replaceAll("\r\n", "\n")) has been add to eliminate the impact of editing the template files from windows machine.
return files.stream().filter(f -> f.getName().equalsIgnoreCase(fileName))
.map(file-> file.getCode().replaceAll("\r\n", "\n")).findFirst().orElse(null);
} catch (Exception e) {
@@ -393,6 +400,43 @@ public class CodeService {
return vertx.fileSystem().readFileBlocking(fileName).toString();
}
+ public List<String> listResources(String resourceFolder, boolean onlyFolders) {
+ List<String> filePaths = new ArrayList<>();
+ try {
+ URI uri = CodeService.class.getResource(resourceFolder).toURI();
+ Path myPath;
+ FileSystem fileSystem = null;
+ if (uri.getScheme().equals("jar")) {
+ fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap());
+ myPath = fileSystem.getPath(resourceFolder);
+ } else {
+ myPath = Paths.get(uri);
+ }
+
+ if (onlyFolders) {
+ // Use Files.walk to list and collect directory paths
+ filePaths = Files.walk(myPath, 10)
+ .filter(Files::isDirectory)
+ .map(path -> path.getFileName().toString())
+ .collect(Collectors.toList());
+ } else {
+ // Use Files.walk to list and collect file paths
+ filePaths = Files.walk(myPath, 1)
+ .filter(Files::isRegularFile)
+ .map(path -> path.getFileName().toString())
+ .collect(Collectors.toList());
+ }
+
+ // Close the file system if opened
+ if (fileSystem != null) {
+ fileSystem.close();
+ }
+ } catch (URISyntaxException | IOException e) {
+ e.printStackTrace();
+ }
+ return filePaths;
+ }
+
public String getFileString(String fullName) {
return vertx.fileSystem().readFileBlocking(fullName).toString();
}
diff --git a/karavan-app/src/main/webui/src/util/ModalDeleteConfirmation.tsx b/karavan-app/src/main/webui/src/util/ModalDeleteConfirmation.tsx
new file mode 100644
index 00000000..ec4d0079
--- /dev/null
+++ b/karavan-app/src/main/webui/src/util/ModalDeleteConfirmation.tsx
@@ -0,0 +1,35 @@
+import React from 'react';
+import {
+ Button,
+ Modal,
+ ModalVariant
+} from '@patternfly/react-core';
+import '../designer/karavan.css';
+
+interface Props {
+ content: string | React.JSX.Element
+ isOpen: boolean
+ onClose: () => void
+ onConfirm: () => void
+ title?: string
+}
+
+export function ModalDeleteConfirmation(props: Props) {
+
+ const {title, isOpen, onClose, onConfirm, content} = props;
+ return (
+ <Modal
+ title={title ? title : 'Confirmation'}
+ variant={ModalVariant.small}
+ isOpen={isOpen}
+ onClose={() => onClose()}
+ actions={[
+ <Button key="confirm" variant="danger" onClick={e => onConfirm()}>Confirm</Button>,
+ <Button key="cancel" variant="link"
+ onClick={e => onClose()}>Cancel</Button>
+ ]}
+ onEscapePress={e => onClose()}>
+ {content}
+ </Modal>
+ )
+}
\ No newline at end of file
diff --git a/karavan-app/src/main/webui/src/util/form-util.css b/karavan-app/src/main/webui/src/util/form-util.css
new file mode 100644
index 00000000..47c4819f
--- /dev/null
+++ b/karavan-app/src/main/webui/src/util/form-util.css
@@ -0,0 +1,12 @@
+.pf-v5-c-modal-box .text-field-with-prefix {
+ gap: 0;
+}
+
+.pf-v5-c-modal-box .text-field-with-prefix .text-field-prefix {
+ margin-top: auto;
+ margin-bottom: auto;
+}
+
+.pf-v5-c-modal-box .text-field-with-prefix .pf-v5-c-text-input-group__text-input {
+ padding-left: 0;
+}
\ No newline at end of file
diff --git a/karavan-app/src/main/webui/src/util/useFormUtil.tsx b/karavan-app/src/main/webui/src/util/useFormUtil.tsx
new file mode 100644
index 00000000..fb7903d8
--- /dev/null
+++ b/karavan-app/src/main/webui/src/util/useFormUtil.tsx
@@ -0,0 +1,130 @@
+import React from 'react';
+import {FieldError, UseFormReturn} from "react-hook-form";
+import {
+ Flex,
+ FormGroup,
+ FormHelperText,
+ FormSelect,
+ FormSelectOption,
+ HelperText,
+ HelperTextItem, Switch, Text,
+ TextInput, TextInputGroup, TextInputGroupMain, TextVariants
+} from "@patternfly/react-core";
+import "./form-util.css"
+
+export function useFormUtil(formContext: UseFormReturn<any>) {
+
+ function getHelper(error: FieldError | undefined) {
+ if (error) {
+ return (
+ <FormHelperText>
+ <HelperText>
+ <HelperTextItem variant={'error'}>
+ {error.message}
+ </HelperTextItem>
+ </HelperText>
+ </FormHelperText>
+ )
+ }
+ }
+
+ function getTextField(fieldName: string, label: string, validate?: ((value: string, formValues: any) => boolean | string) | Record<string, (value: string, formValues: any) => boolean | string>) {
+ const {setValue, getValues, register, formState: {errors}} = formContext;
+ return (
+ <FormGroup label={label} fieldId={fieldName} isRequired>
+ <TextInput className="text-field" type="text" id={fieldName}
+ value={getValues()[fieldName]}
+ validated={!!errors[fieldName] ? 'error' : 'default'}
+ {...register(fieldName, {required: "Required field", validate: validate})}
+ onChange={(e, v) => {
+ setValue(fieldName, v, {shouldValidate: true});
+ }}
+ />
+ {getHelper((errors as any)[fieldName])}
+ </FormGroup>
+ )
+ }
+
+ function getTextFieldPrefix(fieldName: string, label: string, prefix: string,
+ required: boolean,
+ validate?: ((value: string, formValues: any) => boolean | string) | Record<string, (value: string, formValues: any) => boolean | string>) {
+ const {setValue, getValues, register, formState: {errors}} = formContext;
+ return (
+ <FormGroup label={label} fieldId={fieldName} isRequired>
+ <TextInputGroup>
+ <TextInputGroupMain className="text-field-with-prefix" type="text" id={fieldName}
+ value={getValues()[fieldName]}
+ // validated={!!errors[fieldName] ? 'error' : 'default'}
+ {...register(fieldName, {required: (required ? "Required field" : false), validate: validate})}
+ onChange={(e, v) => {
+ setValue(fieldName, v, {shouldValidate: true});
+ }}
+ >
+ <Text className='text-field-prefix' component={TextVariants.p}>{prefix}</Text>
+ </TextInputGroupMain>
+ </TextInputGroup>
+ {getHelper((errors as any)[fieldName])}
+ </FormGroup>
+ )
+ }
+
+ function getFormSelect(fieldName: string, label: string, options: [string, string][]) {
+ const {register, watch, setValue, formState: {errors}} = formContext;
+ return (
+ <FormGroup label={label} fieldId={fieldName} isRequired>
+ <FormSelect
+ ouiaId={fieldName}
+ validated={!!errors[fieldName] ? 'error' : 'default'}
+ value={watch(fieldName)}
+ {...register(fieldName, {required: "Required field"})}
+ onChange={(e, v) => {
+ setValue(fieldName, v, {shouldValidate: true});
+ }}
+ name={fieldName}
+
+ >
+ <FormSelectOption key='placeholder' value={undefined} label='Select one' isDisabled/>
+ {options.map((option, index) => (
+ <FormSelectOption key={index} value={option[0]} label={option[1]}/>
+ ))}
+ </FormSelect>
+ {getHelper((errors as any)[fieldName])}
+ </FormGroup>
+ )
+ }
+
+ function getSwitches(fieldName: string, label: string, options: [string, string][]) {
+ const {watch, register, getValues, setValue, formState: {errors}} = formContext;
+ return (
+ <FormGroup label={label} fieldId={fieldName} isRequired {...register(fieldName)}>
+ <Flex direction={{default: 'column'}}>
+ {options.map((option, index) => {
+ const key = option[0];
+ const label = option[0];
+ return (<Switch
+ id={key}
+ label={label}
+ labelOff={label}
+ isChecked={watch(fieldName) !== undefined && watch(fieldName).includes(key)}
+ onChange={(e, v) => {
+ const vals: string[] = watch(fieldName);
+ const idx = vals.findIndex(x => x === key);
+ if (idx > -1 && !v) {
+ vals.splice(idx, 1);
+ setValue(fieldName, [...vals]);
+ } else if (idx === -1 && v) {
+ vals.push(key);
+ setValue(fieldName, [...vals]);
+ }
+ }}
+ ouiaId={option[0]}
+ />)
+ })}
+ </Flex>
+ </FormGroup>
+ )
+ }
+
+ return {getFormSelect, getTextField, getSwitches, getTextFieldPrefix}
+}
+