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 2131158 OpenAPi JSON import (#415) 2131158 is described below commit 2131158bd635fd1c6e20782a6132e6abaa7835ef Author: Marat Gubaidullin <marat.gubaidul...@gmail.com> AuthorDate: Wed Jul 13 16:09:55 2022 -0400 OpenAPi JSON import (#415) --- .../camel/karavan/api/ProjectFileResource.java | 28 +++- karavan-app/src/main/webapp/src/Main.tsx | 3 - karavan-app/src/main/webapp/src/api/KaravanApi.tsx | 8 +- .../main/webapp/src/integrations/DesignerPage.tsx | 156 ------------------- .../webapp/src/integrations/IntegrationCard.tsx | 54 ------- .../webapp/src/integrations/IntegrationPage.tsx | 172 --------------------- .../main/webapp/src/integrations/OpenApiPage.tsx | 89 ----------- .../main/webapp/src/projects/CreateFileModal.tsx | 6 +- .../src/main/webapp/src/projects/ProjectPage.tsx | 4 +- .../src/main/webapp/src/projects/UploadModal.tsx | 46 +++--- karavan-builder/openshift/karavan-acl.yaml | 22 ++- karavan-builder/openshift/karavan-app.yaml | 3 + 12 files changed, 81 insertions(+), 510 deletions(-) diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectFileResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectFileResource.java index cf40128..0495efe 100644 --- a/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectFileResource.java +++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectFileResource.java @@ -17,6 +17,7 @@ package org.apache.camel.karavan.api; import org.apache.camel.karavan.model.ProjectFile; +import org.apache.camel.karavan.service.GeneratorService; import org.apache.camel.karavan.service.InfinispanService; import javax.inject.Inject; @@ -39,11 +40,14 @@ public class ProjectFileResource { @Inject InfinispanService infinispanService; + @Inject + GeneratorService generatorService; + @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{projectId}") public List<ProjectFile> get(@HeaderParam("username") String username, - @PathParam("projectId") String projectId) throws Exception { + @PathParam("projectId") String projectId) throws Exception { return infinispanService.getProjectFiles(projectId); } @@ -59,11 +63,29 @@ public class ProjectFileResource { @Produces(MediaType.APPLICATION_JSON) @Path("/{project}/{filename}") public void delete(@HeaderParam("username") String username, - @PathParam("project") String project, - @PathParam("filename") String filename) throws Exception { + @PathParam("project") String project, + @PathParam("filename") String filename) throws Exception { infinispanService.deleteProjectFile( URLDecoder.decode(project, StandardCharsets.UTF_8.toString()), URLDecoder.decode(filename, StandardCharsets.UTF_8.toString()) ); } + + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/openapi/{generateRest}/{generateRoutes}/{integrationName}") + public ProjectFile saveOpenapi(@HeaderParam("username") String username, + @PathParam("integrationName") String integrationName, + @PathParam("generateRest") boolean generateRest, + @PathParam("generateRoutes") boolean generateRoutes, ProjectFile file) throws Exception { + infinispanService.saveProjectFile(file); + if (generateRest) { + String yaml = generatorService.generate(file.getCode(), generateRoutes); + ProjectFile integration = new ProjectFile(integrationName, yaml, file.getProjectId()); + infinispanService.saveProjectFile(integration); + return file; + } + return file; + } } \ No newline at end of file diff --git a/karavan-app/src/main/webapp/src/Main.tsx b/karavan-app/src/main/webapp/src/Main.tsx index f34cad6..4e718cf 100644 --- a/karavan-app/src/main/webapp/src/Main.tsx +++ b/karavan-app/src/main/webapp/src/Main.tsx @@ -23,7 +23,6 @@ import {ComponentApi} from "karavan-core/lib/api/ComponentApi"; import Icon from "./Logo"; import {ComponentsPage} from "./components/ComponentsPage"; import {EipPage} from "./eip/EipPage"; -import {OpenApiPage} from "./integrations/OpenApiPage"; import {ProjectsPage} from "./projects/ProjectsPage"; import {Project} from "./models/ProjectModels"; import {ProjectPage} from "./projects/ProjectPage"; @@ -232,8 +231,6 @@ export class Main extends React.Component<Props, State> { {this.state.pageId === 'kamelets' && <KameletsPage dark={false}/>} {this.state.pageId === 'components' && <ComponentsPage dark={false}/>} {this.state.pageId === 'eip' && <EipPage dark={false}/>} - {this.state.pageId === 'openapi' && - <OpenApiPage dark={false} openapi={this.state.openapi} filename={this.state.filename}/>} </FlexItem> </Flex> <Modal diff --git a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx index 239d688..a1146bd 100644 --- a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx +++ b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx @@ -294,10 +294,10 @@ export const KaravanApi = { }); }, - postOpenApi: async (name: string, json: string, generateRest: boolean, generateRoutes: boolean, integrationName: string, after: (res: AxiosResponse<any>) => void) => { - const uri = `/openapi/${name}/${generateRest}/${generateRoutes}/${integrationName}`; - axios.post(encodeURI(uri), json, - {headers: {'Accept': 'text/plain', 'Content-Type': 'text/plain', 'username': 'cameleer'}}) + postOpenApi: async (file: ProjectFile, generateRest: boolean, generateRoutes: boolean, integrationName: string, after: (res: AxiosResponse<any>) => void) => { + const uri = `/file/openapi/${generateRest}/${generateRoutes}/${integrationName}`; + axios.post(encodeURI(uri), file, + {headers: {'Accept': 'application/json', 'Content-Type': 'application/json', 'username': 'cameleer'}}) .then(res => { after(res); }).catch(err => { diff --git a/karavan-app/src/main/webapp/src/integrations/DesignerPage.tsx b/karavan-app/src/main/webapp/src/integrations/DesignerPage.tsx deleted file mode 100644 index 536e413..0000000 --- a/karavan-app/src/main/webapp/src/integrations/DesignerPage.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import React from 'react'; -import { - Button, CodeBlock, CodeBlockCode, - PageSection, Text, TextContent, ToggleGroup, ToggleGroupItem, Toolbar, ToolbarContent, ToolbarItem -} from '@patternfly/react-core'; -import PublishIcon from '@patternfly/react-icons/dist/esm/icons/openshift-icon'; -import DownloadIcon from '@patternfly/react-icons/dist/esm/icons/download-icon'; -import SaveIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; -import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; -import '../designer/karavan.css'; -import {MainToolbar} from "../MainToolbar"; -import {Integration} from "karavan-core/lib/model/IntegrationDefinition"; -import {KaravanApi} from "../api/KaravanApi"; -import {CamelDefinitionYaml} from "karavan-core/lib/api/CamelDefinitionYaml"; -import {KaravanDesigner} from "../designer/KaravanDesigner"; -import FileSaver from "file-saver"; -import Editor from '@monaco-editor/react'; - -interface Props { - integration: Integration, - mode: 'local' | 'gitops' | 'serverless', -} - -interface State { - integration: Integration - view: "design" | "code" - name: string - yaml: string - key: string -} - -export class DesignerPage extends React.Component<Props, State> { - - public state: State = { - integration: this.props.integration, // CamelDefinitionYaml.demo(), - view: "design", - key: "", - name: this.props.integration.metadata.name, - yaml: CamelDefinitionYaml.integrationToYaml(this.props.integration) - }; - - componentDidMount() { - } - - post = () => { - // KaravanApi.postIntegrations(this.state.integration.metadata.name, this.state.yaml, res => { - // if (res.status === 200) { - // console.log(res) //TODO show notification - // } else { - // console.log(res) //TODO show notification - // } - // }) - } - - publish = () => { - // KaravanApi.publishIntegration(this.state.integration.metadata.name, this.state.yaml, res => { - // if (res.status === 200) { - // console.log(res) //TODO show notification - // } else { - // console.log(res) //TODO show notification - // } - // }) - } - - copy = () => { - this.copyToClipboard(this.state.yaml); - } - - copyToClipboard = (data: string) => { - navigator.clipboard.writeText(data); - } - - changeView = (view: "design" | "code") => { - this.setState({view: view}); - } - - save = (name: string, yaml: string) => { - this.setState({name: name, yaml: yaml}) - } - - download = () => { - const file = new File([this.state.yaml], this.state.integration.metadata.name, {type: "application/yaml;charset=utf-8"}); - FileSaver.saveAs(file); - } - - tools = (view: "design" | "code") => ( - <Toolbar id="toolbar-group-types"> - <ToolbarContent> - <ToolbarItem> - <Button variant="secondary" icon={<CopyIcon/>} onClick={e => this.copy()}>Copy</Button> - </ToolbarItem> - <ToolbarItem> - <Button variant="secondary" icon={<DownloadIcon/>} onClick={e => this.download()}>Download</Button> - </ToolbarItem> - {this.props.mode === 'gitops' && - <ToolbarItem> - <Button variant="secondary" icon={<PublishIcon/>} onClick={e => this.publish()}>Publish</Button> - </ToolbarItem> - } - {this.props.mode === 'serverless' && - <ToolbarItem> - <Button variant="primary" icon={<PublishIcon/>} onClick={e => this.post()}>Apply</Button> - </ToolbarItem> - } - {this.props.mode !== 'serverless' && - <ToolbarItem> - <Button variant="secondary" icon={<SaveIcon/>} onClick={e => this.post()}>Save</Button> - </ToolbarItem> - } - </ToolbarContent> - </Toolbar>); - - title = (view: "design" | "code") => ( - <div className="dsl-title"> - <TextContent className="title"> - <Text component="h1">Designer</Text> - </TextContent> - <ToggleGroup aria-label="Switch view" className="toggle"> - <ToggleGroupItem text="Design" buttonId="design" isSelected={view === 'design'} - onChange={e => this.changeView('design')}/> - <ToggleGroupItem text="YAML" buttonId="yaml" isSelected={view === 'code'} - onChange={e => this.changeView('code')}/> - </ToggleGroup> - </div> - ); - - render() { - const {view, yaml, name, key} = this.state; - - return (<> - <MainToolbar title={this.title(view)} - tools={this.tools(view)}/> - {view === 'code' && - <Editor - height="100vh" - defaultLanguage={'yaml'} - theme={'light'} - value={yaml} - className={'code-editor'} - onChange={(value, ev) => {if (value) this.setState({yaml: value})}} - /> - } - {view === 'design' && - <KaravanDesigner - showStartHelp={false} - dark={false} - key={key} - filename={name} - yaml={yaml} - onSave={(name, yaml) => this.save(name, yaml)} - /> - } - </> - ); - } -} diff --git a/karavan-app/src/main/webapp/src/integrations/IntegrationCard.tsx b/karavan-app/src/main/webapp/src/integrations/IntegrationCard.tsx deleted file mode 100644 index ef1142f..0000000 --- a/karavan-app/src/main/webapp/src/integrations/IntegrationCard.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import { - CardHeader, Card, CardTitle, CardBody, Button, CardActions, CardFooter, -} from '@patternfly/react-core'; -import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon"; -import '../designer/karavan.css'; -import {CamelUi} from "../designer/utils/CamelUi"; -import {getDesignerIcon} from "../designer/utils/KaravanIcons"; - -interface Props { - name: string, - type: 'integration' | 'openapi', - status?: string, - onClick: (filename: string, type: 'integration' | 'openapi') => void - onDelete: (name: string, type: 'integration' | 'openapi') => void -} - -interface State { -} - -export class IntegrationCard extends React.Component<Props, State> { - - public state: State = { - }; - - private click(evt: React.MouseEvent) { - evt.stopPropagation(); - this.props.onClick.call(this, this.props.name, this.props.type) - } - - private delete(evt: React.MouseEvent) { - evt.stopPropagation(); - this.props.onDelete.call(this, this.props.name, this.props.type); - } - - render() { - return ( - <Card isCompact key={this.props.name} className="integration-card" onClick={event => this.click(event)}> - <CardHeader> - {getDesignerIcon(this.props.type === 'integration' ? 'routes' : 'rest')} - <CardActions> - <Button variant="link" className="delete-button" onClick={e => this.delete(e)}><DeleteIcon/></Button> - </CardActions> - </CardHeader> - <CardTitle>{this.props.type === 'integration' ? 'Integration' : 'OpenAPI'}</CardTitle> - <CardTitle>{CamelUi.titleFromName(this.props.name)}</CardTitle> - <CardBody>{this.props.name}</CardBody> - <CardFooter className={this.props.status === 'Running' ? 'running' : (this.props.status === 'Error' ? 'error' : 'normal')}> - {this.props.status} - </CardFooter> - </Card> - ); - } -} \ No newline at end of file diff --git a/karavan-app/src/main/webapp/src/integrations/IntegrationPage.tsx b/karavan-app/src/main/webapp/src/integrations/IntegrationPage.tsx deleted file mode 100644 index ebc9506..0000000 --- a/karavan-app/src/main/webapp/src/integrations/IntegrationPage.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import React from 'react'; -import { - Toolbar, - ToolbarContent, - Gallery, - ToolbarItem, - TextInput, - PageSection, - TextContent, - Text, - Button, Modal, FormGroup, ModalVariant, Switch, Form, FormSelect, FormSelectOption, FileUpload -} from '@patternfly/react-core'; -import '../designer/karavan.css'; -import {IntegrationCard} from "./IntegrationCard"; -import {MainToolbar} from "../MainToolbar"; -import RefreshIcon from '@patternfly/react-icons/dist/esm/icons/sync-alt-icon'; -import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon'; -import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; -import {Integration} from "karavan-core/lib/model/IntegrationDefinition"; -import {CamelUi} from "../designer/utils/CamelUi"; -import {UploadModal} from "../projects/UploadModal"; - -interface Props { - integrations: Map<string, string> - openapis: Map<string, string> - onSelect: (filename: string, type: 'integration' | 'openapi') => void - onCreate: any - onDelete: (name: string, type: 'integration' | 'openapi') => void - onRefresh: any -} - -interface State { - repository: string, - path: string, - integrations: Map<string, string>, - openapis: Map<string, string>, - isCreateModalOpen: boolean, - isUploadModalOpen: boolean, - newName: string - crd: boolean - data: string - filename: string - isLoading: boolean - isRejected: boolean - generateRest: boolean - generateRoutes: boolean -} - -export class IntegrationPage extends React.Component<Props, State> { - - public state: State = { - repository: '', - path: '', - integrations: this.props.integrations, - openapis: this.props.openapis, - isCreateModalOpen: false, - isUploadModalOpen: false, - newName: '', - crd: true, - data: '', - filename: '', - isLoading: false, - isRejected: false, - generateRest: true, - generateRoutes: true - }; - - tools = () => (<Toolbar id="toolbar-group-types"> - <ToolbarContent> - <ToolbarItem> - <TextInput className="text-field" type="search" id="search" name="search" - autoComplete="off" placeholder="Search by name"/> - </ToolbarItem> - <ToolbarItem> - <Button variant="secondary" icon={<RefreshIcon/>} - onClick={e => this.props.onRefresh.call(this)}>Refresh</Button> - </ToolbarItem> - <ToolbarItem> - <Button variant="secondary" icon={<UploadIcon/>} - onClick={e => this.setState({isUploadModalOpen: true})}>Upload</Button> - </ToolbarItem> - <ToolbarItem> - <Button icon={<PlusIcon/>} onClick={e => this.setState({isCreateModalOpen: true})}>Create</Button> - </ToolbarItem> - </ToolbarContent> - </Toolbar>); - - title = () => (<TextContent> - <Text component="h1">Integrations</Text> - </TextContent>); - - closeModal = () => { - this.setState({isCreateModalOpen: false, newName: "", isUploadModalOpen: false}); - this.props.onRefresh.call(this); - } - - saveAndCloseCreateModal = () => { - const name = CamelUi.nameFromTitle(this.state.newName) + ".yaml"; - const i = Integration.createNew(name); - i.crd = this.state.crd; - this.props.onCreate.call(this, i); - this.setState({isCreateModalOpen: false, newName: ""}); - } - - onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): void => { - if (event.key === 'Enter' && this.state.newName !== undefined) { - this.saveAndCloseCreateModal(); - } - } - - createModalForm() { - return ( - <Modal - title="Create new Integration" - variant={ModalVariant.small} - isOpen={this.state.isCreateModalOpen} - onClose={this.closeModal} - onKeyDown={this.onKeyDown} - actions={[ - <Button key="confirm" variant="primary" onClick={this.saveAndCloseCreateModal}>Save</Button>, - <Button key="cancel" variant="secondary" onClick={this.closeModal}>Cancel</Button> - ]} - > - <Form isHorizontal={true}> - <FormGroup label="Title" fieldId="title" isRequired> - <TextInput className="text-field" type="text" id="title" name="title" - value={this.state.newName} - onChange={e => this.setState({newName: e})}/> - </FormGroup> - <FormGroup label="Type" fieldId="crd" isRequired> - <FormSelect value={this.state.crd} - onChange={value => this.setState({crd: Boolean(JSON.parse(value))})} - aria-label="FormSelect Input"> - <FormSelectOption key="crd" value="true" label="Camel-K CRD"/> - <FormSelectOption key="plain" value="false" label="Plain YAML"/> - </FormSelect> - </FormGroup> - </Form> - </Modal> - ) - } - - render() { - return ( - <PageSection padding={{default: 'noPadding'}}> - <MainToolbar title={this.title()} tools={this.tools()}/> - <PageSection isFilled className="integration-page"> - <Gallery hasGutter> - {Array.from(this.state.integrations.keys()).map(key => ( - <IntegrationCard key={key} - name={key} - type={"integration"} - status={this.state.integrations.get(key)} - onDelete={this.props.onDelete} - onClick={this.props.onSelect}/> - ))} - {Array.from(this.state.openapis.keys()).map(key => ( - <IntegrationCard key={key} - name={key} - type={"openapi"} - status={this.state.openapis.get(key)} - onDelete={this.props.onDelete} - onClick={this.props.onSelect}/> - ))} - </Gallery> - </PageSection> - {this.createModalForm()} - <UploadModal isOpen={this.state.isUploadModalOpen} onClose={this.closeModal}/> - </PageSection> - ); - } -}; \ No newline at end of file diff --git a/karavan-app/src/main/webapp/src/integrations/OpenApiPage.tsx b/karavan-app/src/main/webapp/src/integrations/OpenApiPage.tsx deleted file mode 100644 index a976ebf..0000000 --- a/karavan-app/src/main/webapp/src/integrations/OpenApiPage.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React from 'react'; -import { - Button, CodeBlock, CodeBlockCode, - PageSection, Text, TextContent, ToggleGroup, ToggleGroupItem, Toolbar, ToolbarContent, ToolbarItem -} from '@patternfly/react-core'; -import PublishIcon from '@patternfly/react-icons/dist/esm/icons/openshift-icon'; -import DownloadIcon from '@patternfly/react-icons/dist/esm/icons/download-icon'; -import SaveIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; -import CopyIcon from '@patternfly/react-icons/dist/esm/icons/copy-icon'; -import '../designer/karavan.css'; -import {MainToolbar} from "../MainToolbar"; -import {Integration} from "karavan-core/lib/model/IntegrationDefinition"; -import {KaravanApi} from "../api/KaravanApi"; -import {CamelDefinitionYaml} from "karavan-core/lib/api/CamelDefinitionYaml"; -import {KaravanDesigner} from "../designer/KaravanDesigner"; -import FileSaver from "file-saver"; -import Editor from '@monaco-editor/react'; - -interface Props { - openapi: string, - filename: string, - dark: boolean -} - -interface State { -} - -export class OpenApiPage extends React.Component<Props, State> { - - public state: State = { - }; - - copy = () => { - this.copyToClipboard(this.props.openapi); - } - - copyToClipboard = (data: string) => { - navigator.clipboard.writeText(data); - } - - changeView = (view: "design" | "code") => { - this.setState({view: view}); - } - - save = (name: string, yaml: string) => { - this.setState({name: name, yaml: yaml}) - } - - download = () => { - const file = new File([this.props.openapi], this.props.filename, {type: "application/json;charset=utf-8"}); - FileSaver.saveAs(file); - } - - tools = () => ( - <Toolbar id="toolbar-group-types"> - <ToolbarContent> - <ToolbarItem> - <Button variant="secondary" icon={<CopyIcon/>} onClick={e => this.copy()}>Copy</Button> - </ToolbarItem> - <ToolbarItem> - <Button variant="secondary" icon={<DownloadIcon/>} onClick={e => this.download()}>Download</Button> - </ToolbarItem> - </ToolbarContent> - </Toolbar>); - - title = () => ( - <div className="dsl-title"> - <TextContent className="title"> - <Text component="h1">OpenAPI</Text> - </TextContent> - </div> - ); - - render() { - return (<> - <MainToolbar title={this.title()} - tools={this.tools()}/> - <Editor - height="100vh" - defaultLanguage={'json'} - theme={'light'} - value={this.props.openapi} - className={'code-editor'} - onChange={(value, ev) => {if (value) this.setState({yaml: value})}} - /> - </> - ); - } -} diff --git a/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx b/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx index bcbf838..aaa5cae 100644 --- a/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx +++ b/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx @@ -41,10 +41,10 @@ export class CreateFileModal extends React.Component<Props, State> { const file = new ProjectFile(filename + '.' + extension, this.props.project.projectId, ''); KaravanApi.postProjectFile(file, res => { if (res.status === 200) { - console.log(res) //TODO show notification + // console.log(res) //TODO show notification this.props.onClose?.call(this); } else { - console.log(res) //TODO show notification + // console.log(res) //TODO show notification this.props.onClose?.call(this); } }) @@ -69,7 +69,7 @@ export class CreateFileModal extends React.Component<Props, State> { <Form autoComplete="off" isHorizontal className="create-file-form"> <FormGroup label="Type" fieldId="type" isRequired> <ToggleGroup aria-label="Type"> - {ProjectFileTypes.filter(p => p.name !== 'PROPERTIES' && p.name !== 'LOG').map(p => { + {ProjectFileTypes.filter(p => !['PROPERTIES', 'LOG'].includes(p.name)).map(p => { const title = p.title + (p.name === 'CODE' ? ' (' + p.extension + ')' : ''); return <ToggleGroupItem key={title} text={title} buttonId={p.name} isSelected={this.state.extension === p.extension} diff --git a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx index a8dcf06..631434c 100644 --- a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx +++ b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx @@ -43,6 +43,7 @@ import {ProjectHeader} from "./ProjectHeader"; import {ProjectModel, ProjectProperty} from "karavan-core/lib/model/ProjectModel"; import {ProjectModelApi} from "karavan-core/lib/api/ProjectModelApi"; import {KubernetesAPI} from "../designer/utils/KubernetesAPI"; +import {UploadModal} from "./UploadModal"; interface Props { project: Project, @@ -424,7 +425,7 @@ export class ProjectPage extends React.Component<Props, State> { const isYaml = file !== undefined && file.name.endsWith("yaml"); const isProperties = file !== undefined && file.name.endsWith("properties"); const isLog = file !== undefined && file.name.endsWith("log"); - const isCode = file !== undefined && (file.name.endsWith("java") || file.name.endsWith("groovy")); + const isCode = file !== undefined && (file.name.endsWith("java") || file.name.endsWith("groovy") || file.name.endsWith("json")); const showDesigner = isYaml && mode === 'design'; const showEditor = isCode || (isYaml && mode === 'code'); return ( @@ -461,6 +462,7 @@ export class ProjectPage extends React.Component<Props, State> { onEscapePress={e => this.setState({isDeleteModalOpen: false})}> <div>{"Are you sure you want to delete the file " + this.state.fileToDelete?.name + "?"}</div> </Modal> + <UploadModal projectId={this.props.project.projectId} isOpen={this.state.isUploadModalOpen} onClose={this.closeModal}/> </PageSection> ) } diff --git a/karavan-app/src/main/webapp/src/projects/UploadModal.tsx b/karavan-app/src/main/webapp/src/projects/UploadModal.tsx index b67a783..d457c51 100644 --- a/karavan-app/src/main/webapp/src/projects/UploadModal.tsx +++ b/karavan-app/src/main/webapp/src/projects/UploadModal.tsx @@ -4,8 +4,11 @@ import { Button, Modal, FormGroup, ModalVariant, Switch, Form, FileUpload, Radio } from '@patternfly/react-core'; import '../designer/karavan.css'; +import {KaravanApi} from "../api/KaravanApi"; +import {ProjectFile} from "../models/ProjectModels"; interface Props { + projectId: string, isOpen: boolean, onClose: any } @@ -40,27 +43,28 @@ export class UploadModal extends React.Component<Props, State> { saveAndCloseModal = () => { const state = this.state; - // if (this.state.type === "integration"){ - // KaravanApi.postIntegrations(state.filename, state.data, res => { - // if (res.status === 200) { - // console.log(res) //TODO show notification - // this.props.onClose?.call(this); - // } else { - // console.log(res) //TODO show notification - // this.props.onClose?.call(this); - // } - // }) - // } else { - // KaravanApi.postOpenApi(state.filename, state.data, state.generateRest, state.generateRoutes, state.integrationName, res => { - // if (res.status === 200) { - // console.log(res) //TODO show notification - // this.props.onClose?.call(this); - // } else { - // console.log(res) //TODO show notification - // this.props.onClose?.call(this); - // } - // }) - // } + const file = new ProjectFile(state.filename, this.props.projectId, state.data); + if (this.state.type === "integration"){ + KaravanApi.postProjectFile(file, res => { + if (res.status === 200) { + //TODO show notification + this.props.onClose?.call(this); + } else { + // TODO show notification + this.props.onClose?.call(this); + } + }) + } else { + KaravanApi.postOpenApi(file, state.generateRest, state.generateRoutes, state.integrationName, res => { + if (res.status === 200) { + console.log(res) //TODO show notification + this.props.onClose?.call(this); + } else { + console.log(res) //TODO show notification + this.props.onClose?.call(this); + } + }) + } } handleFileInputChange = (event: React.ChangeEvent<HTMLInputElement> | React.DragEvent<HTMLElement>, file: File) => this.setState({filename: file.name}); diff --git a/karavan-builder/openshift/karavan-acl.yaml b/karavan-builder/openshift/karavan-acl.yaml index 88088a9..7670950 100644 --- a/karavan-builder/openshift/karavan-acl.yaml +++ b/karavan-builder/openshift/karavan-acl.yaml @@ -7,11 +7,11 @@ metadata: app.kubernetes.io/name: karavan app.openshift.io/runtime: camel --- -# Role view-secrets +# Role karavan-app apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - name: karavan-view-secrets + name: karavan-app rules: - apiGroups: - "" @@ -21,6 +21,20 @@ rules: verbs: - get - list + - apiGroups: + - "" + - apps.openshift.io + resources: + - deploymentconfigs + - replicationcontrollers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch --- # Role tekton run pipeline kind: Role @@ -68,11 +82,11 @@ subjects: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: karavan-view-secrets + name: karavan-app roleRef: kind: Role apiGroup: rbac.authorization.k8s.io - name: karavan-view-secrets + name: karavan-app subjects: - kind: ServiceAccount name: karavan diff --git a/karavan-builder/openshift/karavan-app.yaml b/karavan-builder/openshift/karavan-app.yaml index a9acc04..bd9353b 100644 --- a/karavan-builder/openshift/karavan-app.yaml +++ b/karavan-builder/openshift/karavan-app.yaml @@ -43,6 +43,9 @@ spec: image: ghcr.io/apache/camel-karavan:0.0.16 imagePullPolicy: Always name: karavan + resources: + requests: + memory: "2048Mi" volumeMounts: - name: karavan-data mountPath: /deployments/karavan-data