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 4c72df72d92704c8ecc5a5d06a3ec2de301de0d3 Author: Marat Gubaidullin <[email protected]> AuthorDate: Wed Jul 3 16:39:25 2024 -0400 Ui Refactor --- karavan-app/src/main/webui/src/api/ProjectStore.ts | 6 ++ .../src/main/webui/src/projects/ProjectsPage.tsx | 51 ++++------------- .../main/webui/src/projects/ProjectsToolbar.tsx | 64 ++++++++++++++++++++++ .../webui/src/util/ModalDeleteConfirmation.tsx | 35 ------------ 4 files changed, 82 insertions(+), 74 deletions(-) diff --git a/karavan-app/src/main/webui/src/api/ProjectStore.ts b/karavan-app/src/main/webui/src/api/ProjectStore.ts index 4cfed44c..07875a26 100644 --- a/karavan-app/src/main/webui/src/api/ProjectStore.ts +++ b/karavan-app/src/main/webui/src/api/ProjectStore.ts @@ -93,6 +93,8 @@ interface ProjectsState { projects: Project[]; setProjects: (projects: Project[]) => void; upsertProject: (project: Project) => void; + filter: string; + setFilter: (filter: string) => void; } export const useProjectsStore = createWithEqualityFn<ProjectsState>((set) => ({ @@ -108,6 +110,10 @@ export const useProjectsStore = createWithEqualityFn<ProjectsState>((set) => ({ ? [...state.projects, project] : [...state.projects.filter(f => f.projectId !== project.projectId), project] })); + }, + filter: '', + setFilter: (filter: string) => { + set({filter: filter}); } }), shallow) diff --git a/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx b/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx index a2028459..b9c23549 100644 --- a/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx +++ b/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx @@ -15,23 +15,17 @@ * limitations under the License. */ -import React, {useEffect, useState} from 'react'; +import React, {useEffect} from 'react'; import { - Toolbar, - ToolbarContent, - ToolbarItem, - TextInput, PageSection, TextContent, Text, - Button, Bullseye, EmptyState, EmptyStateVariant, EmptyStateIcon, EmptyStateHeader } from '@patternfly/react-core'; import './ProjectsPage.css'; -import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon'; import { Tbody, Td, @@ -51,46 +45,25 @@ import {MainToolbar} from "../designer/MainToolbar"; import {Project, ProjectType} from "../api/ProjectModels"; import {shallow} from "zustand/shallow"; import {KaravanApi} from "../api/KaravanApi"; -import RefreshIcon from "@patternfly/react-icons/dist/esm/icons/sync-alt-icon"; -import {ProjectService} from "../api/ProjectService"; +import {ProjectsToolbar} from "./ProjectsToolbar"; -export function ProjectsPage () { +interface Props { + tools?: React.ReactNode +} - const [projects, setProjects] = useProjectsStore((s) => [s.projects, s.setProjects], shallow) - const [operation, setProject] = useProjectStore((s) => [s.operation, s.setProject], shallow) - const [filter, setFilter] = useState<string>(''); +export function ProjectsPage (props: Props) { + + const [projects, setProjects, filter, setFilter] + = useProjectsStore((s) => [s.projects, s.setProjects, s.filter, s.setFilter], shallow) + const [operation] = useProjectStore((s) => [s.operation], shallow) useEffect(() => { KaravanApi.getProjects((projects: Project[]) => { setProjects(projects); + setFilter(''); }); }, []); - function getTools() { - return <Toolbar id="toolbar-group-types"> - <ToolbarContent> - <ToolbarItem> - <Button icon={<RefreshIcon/>} - variant={"link"} - onClick={e => ProjectService.refreshProjects()} - /> - </ToolbarItem> - <ToolbarItem> - <TextInput className="text-field" type="search" id="search" name="search" - autoComplete="off" placeholder="Search by name" - value={filter} - onChange={(_, e) => setFilter(e)}/> - </ToolbarItem> - <ToolbarItem> - <Button className="dev-action-button" - icon={<PlusIcon/>} - onClick={e => - setProject(new Project(), 'create')} - >Create</Button> - </ToolbarItem> - </ToolbarContent> - </Toolbar> - } function title() { return <TextContent> @@ -143,7 +116,7 @@ export function ProjectsPage () { return ( <PageSection className="projects-page" padding={{default: 'noPadding'}}> <PageSection className="tools-section" padding={{default: 'noPadding'}}> - <MainToolbar title={title()} tools={getTools()}/> + <MainToolbar title={title()} tools={props.tools ? props.tools : <ProjectsToolbar/>}/> </PageSection> <PageSection isFilled className="project-section"> {getProjectsTable()} diff --git a/karavan-app/src/main/webui/src/projects/ProjectsToolbar.tsx b/karavan-app/src/main/webui/src/projects/ProjectsToolbar.tsx new file mode 100644 index 00000000..530fa348 --- /dev/null +++ b/karavan-app/src/main/webui/src/projects/ProjectsToolbar.tsx @@ -0,0 +1,64 @@ +/* + * 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 { + Toolbar, + ToolbarContent, + ToolbarItem, + TextInput, + Button, +} from '@patternfly/react-core'; +import './ProjectsPage.css'; +import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon'; +import {useProjectsStore, useProjectStore} from "../api/ProjectStore"; +import {Project} from "../api/ProjectModels"; +import {shallow} from "zustand/shallow"; +import RefreshIcon from "@patternfly/react-icons/dist/esm/icons/sync-alt-icon"; +import {ProjectService} from "../api/ProjectService"; + +export function ProjectsToolbar () { + + const [filter, setFilter] = useProjectsStore((s) => [s.filter, s.setFilter], shallow) + const [setProject] = useProjectStore((s) => [s.setProject], shallow) + + return ( + <Toolbar id="toolbar-group-types"> + <ToolbarContent> + <ToolbarItem> + <Button icon={<RefreshIcon/>} + variant={"link"} + onClick={e => ProjectService.refreshProjects()} + /> + </ToolbarItem> + <ToolbarItem> + <TextInput className="text-field" type="search" id="search" name="search" + autoComplete="off" placeholder="Search by name" + value={filter} + onChange={(_, e) => setFilter(e)}/> + </ToolbarItem> + <ToolbarItem> + <Button className="dev-action-button" + icon={<PlusIcon/>} + onClick={e => + setProject(new Project(), 'create')} + >Create</Button> + </ToolbarItem> + </ToolbarContent> + </Toolbar> + ) +} \ No newline at end of file diff --git a/karavan-app/src/main/webui/src/util/ModalDeleteConfirmation.tsx b/karavan-app/src/main/webui/src/util/ModalDeleteConfirmation.tsx deleted file mode 100644 index ec4d0079..00000000 --- a/karavan-app/src/main/webui/src/util/ModalDeleteConfirmation.tsx +++ /dev/null @@ -1,35 +0,0 @@ -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
