diff --git a/docker-compose.yml b/docker-compose.yml index 12eec75..c4558f2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -107,10 +107,11 @@ services: - POSTGRES_USER=root - POSTGRES_PASSWORD=root - POSTGRES_DB=orca + # - PGDATA=/var/lib/postgresql/data/some_name/ ports: - "5433:5432" volumes: - - ./data:/var/lib/postgresql/data + - ./data/pg-data:/var/lib/postgresql/data container_name: postgres-ser ### Redis ################################################ diff --git a/web/src/core/components/dropdown/dropdown.css b/web/src/core/components/dropdown/dropdown.css new file mode 100644 index 0000000..1735f7d --- /dev/null +++ b/web/src/core/components/dropdown/dropdown.css @@ -0,0 +1,100 @@ +.dropdown { + position: relative; + color: #333; + cursor: default; + } + + .dropdown .arrow { + border-color: #999 transparent transparent; + border-style: solid; + border-width: 5px 5px 0; + content: " "; + display: block; + height: 0; + margin-top: 0.3rem; + position: absolute; + right: 10px; + top: 14px; + width: 0; + } + + .dropdown .arrow.open { + border-color: transparent transparent #999; + border-width: 0 5px 5px; + } + + .input { + line-height: 1.5; + font-size: 1rem; + background-color: #fff; + border: 1px solid #ccc; + border-radius: 2px; + box-sizing: border-box; + cursor: default; + outline: none; + padding: 8px 52px 8px 10px; + transition: all 200ms ease; + width: 100%; + } + + .dropdown .options { + display: none; + background-color: #fff; + border: 1px solid #ccc; + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06); + box-sizing: border-box; + margin-top: -1px; + max-height: 200px; + overflow-y: auto; + position: absolute; + top: 100%; + width: 100%; + z-index: 1000; + -webkit-overflow-scrolling: touch; + } + + .dropdown .options.open { + display: block; + } + + .dropdown .option { + box-sizing: border-box; + color: rgba(51, 51, 51, 0.8); + cursor: pointer; + display: block; + padding: 8px 10px; + } + + .dropdown .option.selected, + .dropdown .option:hover { + background-color: #f2f9fc; + color: #333; + } + + .close { + position: absolute; + right: 40px; + top: 14px; + width: 16px; + height: 16px; + opacity: 0.3; + } + .close:hover { + opacity: 1; + } + .close:before, .close:after { + position: absolute; + left: 15px; + content: ' '; + height: 16px; + width: 2px; + background-color: #333; + } + .close:before { + transform: rotate(45deg); + } + .close:after { + transform: rotate(-45deg); + } + + \ No newline at end of file diff --git a/web/src/core/components/dropdown/index.jsx b/web/src/core/components/dropdown/index.jsx new file mode 100644 index 0000000..0d7f686 --- /dev/null +++ b/web/src/core/components/dropdown/index.jsx @@ -0,0 +1,97 @@ +import { useEffect, useRef, useState } from "react"; +import PropTypes from "prop-types"; +import "./dropdown.css"; + + + +export const SearchableDropdown = ({ + options, + label, + id, + selectedValue, + handleChange +}) => { + const [query, setQuery] = useState(""); + const [isOpen, setIsOpen] = useState(false); + + const inputRef = useRef(null); + + useEffect(() => { + document.addEventListener("click", toggle); + return () => document.removeEventListener("click", toggle); + }, []); + + const selectOption = (option) => { + setQuery(() => ""); + handleChange(option); + setIsOpen((isOpen) => !isOpen); + }; + + function toggle(e) { + setIsOpen(e && e.target === inputRef.current); + } + + const getDisplayValue = () => { + if (query) return query; + if (selectedValue) return selectedValue[label] || ""; + + return ""; + }; + + const filter = (options) => { + return options.filter( + (option) => option[label].toLowerCase().indexOf(query.toLowerCase()) > -1 + ); + }; + + return ( +
+
+
+ { + setQuery(e.target.value); + handleChange(null); + }} + onClick={toggle} + /> +
+ {selectedValue[label] &&
handleChange({})}/>} +
+
+ +
+ {filter(options).map((option, index) => { + return ( +
selectOption(option)} + className={`option ${ + option === selectedValue ? "selected" : "" + }`} + key={`${id}-${index}`} + > + {option[label]} +
+ ); + })} +
+
+ ); +}; + +SearchableDropdown.propTypes = { + options: PropTypes.arrayOf(PropTypes.object), + label: PropTypes.string, + id: PropTypes.string, + selectedValue: PropTypes.object, + handleChange: PropTypes.func + }; + + + diff --git a/web/src/core/components/flow/components/new.tsx b/web/src/core/components/flow/components/new.tsx index 7cbb62e..1d7da8f 100644 --- a/web/src/core/components/flow/components/new.tsx +++ b/web/src/core/components/flow/components/new.tsx @@ -11,21 +11,21 @@ import { shallow } from "zustand/shallow"; export const New: React.FC = () => { let options = [ - { - key: "loop", - label: "Loop", - icon: - }, - { - key: "ifcondition", - label: "If Condidion", - icon: - }, - { - key: "block", - label: "Block", - icon: - }, + // { + // key: "loop", + // label: "Loop", + // icon: + // }, + // { + // key: "ifcondition", + // label: "If Condidion", + // icon: + // }, + // { + // key: "block", + // label: "Block", + // icon: + // }, { key: "action_group", label: "Action group", diff --git a/web/src/core/components/flow/form.tsx b/web/src/core/components/flow/form.tsx index 0f66a84..8e818a3 100644 --- a/web/src/core/components/flow/form.tsx +++ b/web/src/core/components/flow/form.tsx @@ -1,10 +1,10 @@ -import {Service} from "service"; -import {Select as OSelect} from "core/components/select"; -import {Endpoint} from "service/endpoint"; -import React, {useEffect, useState} from "react"; -import {useFlowStore} from "stores/flow.store"; -import {shallow} from "zustand/shallow"; -import {useParams} from "react-router-dom"; +import { Service } from "service"; +import { Endpoint } from "service/endpoint"; +import { useEffect, useState } from "react"; +import { useFlowStore } from "stores/flow.store"; +import { shallow } from "zustand/shallow"; +import { useParams } from "react-router-dom"; +import { SearchableDropdown } from "core/components/dropdown/index.jsx"; export interface WorkflowFormParm { title: string; @@ -14,6 +14,7 @@ export const WorkflowForm: React.FC = ({title}) => { const [obj, setObject] = useState({} as any); const {appId = ""} = useParams(); const [dataSource, setDataSource] = useState([] as any); + const [actionGroup, setActionGroup] = useState({}); const {nodes, edges, currentNode} = useFlowStore( (state: any) => ({ nodes: state.nodes, @@ -46,47 +47,27 @@ export const WorkflowForm: React.FC = ({title}) => { // console.log(currentNode); }, []); - return ( - <> -
-
-

- {obj.name} -

-
-
-
- { - console.log(value); - // row["kind"] = value["key"]; - }} - render={(row: any) => { - return {row["name"]}; - }} - > - {/* */} - {/* */} - {/* - - - - {(dataSource || []).map((item: any) => { - return {item.name}; - })} - - - */} -
- - ); + return ( + <> +
+
+

+ {obj.name} +

+
+
+
+
Select action group
+ { + setActionGroup(val) + }} + /> +
+ + ); }; diff --git a/web/src/core/components/flow/node/new.tsx b/web/src/core/components/flow/node/new.tsx index 86fb1a9..4c4da13 100644 --- a/web/src/core/components/flow/node/new.tsx +++ b/web/src/core/components/flow/node/new.tsx @@ -27,21 +27,21 @@ type MyObject = { [key: string]: () => any }; export const NewNode: React.FC = ({ data, xPos, yPos }) => { const options: Array