#164: Made autocompleter better

This commit is contained in:
frikky
2020-09-26 21:04:46 +02:00
parent 7a24be4da3
commit 90f33d95b5
4 changed files with 234 additions and 108 deletions
+224 -108
View File
@@ -36,6 +36,7 @@ import CircularProgress from '@material-ui/core/CircularProgress';
import Switch from '@material-ui/core/Switch';
import ReactJson from 'react-json-view'
import { useBeforeunload } from 'react-beforeunload';
import NestedMenuItem from "material-ui-nested-menu-item";
import ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';
import CachedIcon from '@material-ui/icons/Cached';
@@ -1395,7 +1396,6 @@ const AngularWorkflow = (props) => {
example = action.example
}
console.log("EXAMPLE: ", example)
node.data.example = example
return node;
@@ -2438,6 +2438,7 @@ const AngularWorkflow = (props) => {
const [actionlist, setActionlist] = React.useState([])
const [jsonList, setJsonList] = React.useState([])
const [showAutocomplete, setShowAutocomplete] = React.useState(false)
const [menuPosition, setMenuPosition] = useState(null)
useEffect(() => {
if (selectedActionParameters !== null && selectedActionParameters.length === 0) {
@@ -2469,6 +2470,7 @@ const AngularWorkflow = (props) => {
}
}
// Loops parent nodes' old results to fix autocomplete
var parents = getParents(selectedAction)
if (parents.length > 1) {
for (var key in parents) {
@@ -2477,8 +2479,39 @@ const AngularWorkflow = (props) => {
continue
}
var exampledata = item.example === undefined ? "" : item.example
// Find previous execution and their variables
if (exampledata === "" && workflowExecutions.length > 0) {
// Look for the ID
const found = false
for (var key in workflowExecutions) {
const foundResult = workflowExecutions[key].results.find(result => result.action.id === item.id)
if (foundResult === undefined) {
continue
}
var jsonvalid = true
try {
const tmp = String(JSON.parse(foundResult.result))
if (!tmp.includes("{") && !tmp.includes("[")) {
jsonvalid = false
}
} catch (e) {
jsonvalid = false
}
// Finds the FIRST json only
if (jsonvalid) {
exampledata = JSON.parse(foundResult.result)
break
} else {
console.log("Invalid JSON: ", foundResult.result)
}
}
}
// 1. Take
const actionvalue = {"type": "action", "id": item.id, "name": item.label, "autocomplete": `${item.label.split(" ").join("_")}`, "example": item.example === undefined ? "" : item.example}
const actionvalue = {"type": "action", "id": item.id, "name": item.label, "autocomplete": `${item.label.split(" ").join("_")}`, "example": exampledata}
actionlist.push(actionvalue)
}
}
@@ -2502,12 +2535,18 @@ const AngularWorkflow = (props) => {
// bad detection mechanism probably
if (event.target.value[event.target.value.length-1] === "." && actionlist.length > 0) {
console.log("GET THE LAST ARGUMENT FOR !")
//const [jsonList, getJsonList] = React.useState([])
console.log("GET THE LAST ARGUMENT FOR NODE!")
// THIS IS AN EXAMPLE OF SHOWING IT
/*
const inputdata = {"data": "1.2.3.4", "dataType": "4.5.6.6"}
const returnJson = GetParsedPaths(inputdata, "")
setJsonList(GetParsedPaths(inputdata, ""))
if (!showDropdown) {
setShowAutocomplete(false)
setShowDropdown(true)
setShowDropdownNumber(count)
}
console.log(jsonList)
*/
// Search for the item backwards
// 1. Reverse search backwards from . -> $
@@ -2693,7 +2732,11 @@ const AngularWorkflow = (props) => {
endAdornment: (
<InputAdornment position="end">
<Tooltip title="Autocomplete text" placement="top">
<AddCircleOutlineIcon style={{cursor: "pointer"}} onClick={() => {
<AddCircleOutlineIcon style={{cursor: "pointer"}} onClick={(event) => {
setMenuPosition({
top: event.pageY,
left: event.pageX,
})
setShowDropdownNumber(count)
setShowDropdown(true)
setShowAutocomplete(true)
@@ -2862,7 +2905,180 @@ const AngularWorkflow = (props) => {
)) : null}
</Select>
}
}
// Shows nested list of nodes > their JSON lists
const ActionlistWrapper = (props) => {
const handleMenuClose = () => {
setShowAutocomplete(false)
if (!selectedActionParameters[count].value[selectedActionParameters[count].value.length-1] === "$") {
setShowDropdown(false)
}
setUpdate(Math.random())
setMenuPosition(null)
}
const handleItemClick = (values) => {
if (values === undefined || values === null || values.length === 0) {
return
}
var toComplete = selectedActionParameters[count].value.trim().endsWith("$") ? values[0].autocomplete : "$"+values[0].autocomplete
for (var key in values) {
if (key == 0 || values[key].autocomplete.length === 0) {
continue
}
toComplete += values[key].autocomplete
}
selectedActionParameters[count].value += toComplete
selectedAction.parameters[count].value = selectedActionParameters[count].value
console.log("TARGET: ", selectedActionParameters)
setSelectedAction(selectedAction)
setUpdate(Math.random())
setShowDropdown(false)
setMenuPosition(null)
}
const iconStyle = {
marginRight: 15,
}
return (
<div >
<Menu
anchorReference="anchorPosition"
anchorPosition={menuPosition}
onClose={() => {
handleMenuClose()
}}
open={!!menuPosition}
style={{
border: `2px solid #f85a3e`,
color: "white",
marginTop: 2,
}}
>
{actionlist.map(innerdata => {
const icon = innerdata.type === "action" ? <AppsIcon style={{marginRight: 10}} /> : innerdata.type === "workflow_variable" || innerdata.type === "execution_variable" ? <FavoriteBorderIcon style={{marginRight: 10}} /> : <ScheduleIcon style={{marginRight: 10}} />
const handleExecArgumentHover = (inside) => {
var exec_text_field = document.getElementById("execution_argument_input_field")
if (exec_text_field !== null) {
if (inside) {
exec_text_field.style.border = "2px solid #f85a3e"
} else {
exec_text_field.style.border = ""
}
}
// Also doing arguments
if (workflow.triggers !== undefined && workflow.triggers !== null && workflow.triggers.length > 0) {
for (var key in workflow.triggers) {
const item = workflow.triggers[key]
var node = cy.getElementById(item.id)
if (node.length > 0) {
if (inside) {
node.addClass('shuffle-hover-highlight')
} else {
node.removeClass('shuffle-hover-highlight')
}
}
}
}
}
const handleActionHover = (inside, actionId) => {
var node = cy.getElementById(actionId)
if (node.length > 0) {
if (inside) {
node.addClass('shuffle-hover-highlight')
} else {
node.removeClass('shuffle-hover-highlight')
}
}
}
const handleMouseover = () => {
if (innerdata.type === "Execution Argument") {
handleExecArgumentHover(true)
} else if (innerdata.type === "action") {
handleActionHover(true, innerdata.id)
}
}
const handleMouseOut = () => {
if (innerdata.type === "Execution Argument") {
handleExecArgumentHover(false)
} else if (innerdata.type === "action") {
handleActionHover(false, innerdata.id)
}
}
var parsedPaths = []
if (typeof(innerdata.example) === "object") {
parsedPaths = GetParsedPaths(innerdata.example, "")
}
return (
parsedPaths.length > 0 ?
<NestedMenuItem
key={innerdata.name}
label={
<div style={{display: "flex"}}>
{icon} {innerdata.name}
</div>
}
parentMenuOpen={!!menuPosition}
style={{backgroundColor: inputColor, color: "white"}}
onClick={() => {
handleItemClick([innerdata])
}}
>
{parsedPaths.map((pathdata, index) => {
// FIXME: Should be recursive in here
const icon = pathdata.type === "value" ? <VpnKeyIcon style={iconStyle} /> : pathdata.type === "list" ? <FormatListNumberedIcon style={iconStyle} /> : <ExpandMoreIcon style={iconStyle} />
return (
<MenuItem key={pathdata.name} style={{backgroundColor: inputColor, color: "white"}} value={pathdata} onMouseOver={() => {}}
onClick={() => {
handleItemClick([innerdata, pathdata])
}}
>
<Tooltip color="primary" title={`Ex. value: ${pathdata.value}`} placement="left">
<div style={{display: "flex"}}>
{icon} {pathdata.name}
</div>
</Tooltip>
</MenuItem>
)
})}
</NestedMenuItem>
:
<MenuItem key={innerdata.name} style={{backgroundColor: inputColor, color: "white"}} value={innerdata} onMouseOver={() => handleMouseover()} onMouseOut={() => {handleMouseOut()}}
onClick={() => {
handleItemClick([innerdata])
}}
>
<Tooltip color="primary" title={`Value: ${innerdata.value}`} placement="left">
<div style={{display: "flex"}}>
{icon} {innerdata.name}
</div>
</Tooltip>
</MenuItem>
)
})}
</Menu>
</div>
)
}
var itemColor = "#f85a3e"
@@ -2942,7 +3158,6 @@ const AngularWorkflow = (props) => {
selectedActionParameters[count].value += e.target.value.autocomplete
selectedAction.parameters[count].value = selectedActionParameters[count].value
console.log("TARGET: ", selectedActionParameters)
setSelectedAction(selectedAction)
setUpdate(Math.random())
@@ -2969,106 +3184,7 @@ const AngularWorkflow = (props) => {
</FormControl>
: null}
{showDropdown && showDropdownNumber === count && data.variant === "STATIC_VALUE" && jsonList.length === 0 ?
<FormControl fullWidth>
<InputLabel id="action-autocompleter" style={{marginLeft: 10, color: "white"}}>Autocomplete</InputLabel>
<Select
labelId="action-autocompleter"
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
onClose={() => {
setShowAutocomplete(false)
if (!selectedActionParameters[count].value[selectedActionParameters[count].value.length-1] === "$") {
setShowDropdown(false)
}
setUpdate(Math.random())
}}
onClick={() => setShowAutocomplete(true)}
open={showAutocomplete}
fullWidth
style={{border: `2px solid #f85a3e`, color: "white", height: 50, marginTop: 2,}}
onChange={(e) => {
console.log("CHANGE!")
const toComplete = selectedActionParameters[count].value.trim().endsWith("$") ? e.target.value.autocomplete : "$"+e.target.value.autocomplete
selectedActionParameters[count].value += toComplete
selectedAction.parameters[count].value = selectedActionParameters[count].value
console.log("TARGET: ", selectedActionParameters)
setSelectedAction(selectedAction)
setUpdate(Math.random())
setShowDropdown(false)
}}
>
{actionlist.map(data => {
const icon = data.type === "action" ? <AppsIcon style={{marginRight: 10}} /> : data.type === "workflow_variable" || data.type === "execution_variable" ? <FavoriteBorderIcon style={{marginRight: 10}} /> : <ScheduleIcon style={{marginRight: 10}} />
const handleExecArgumentHover = (inside) => {
var exec_text_field = document.getElementById("execution_argument_input_field")
if (exec_text_field !== null) {
if (inside) {
exec_text_field.style.border = "2px solid #f85a3e"
} else {
exec_text_field.style.border = ""
}
}
// Also doing arguments
if (workflow.triggers !== undefined && workflow.triggers !== null && workflow.triggers.length > 0) {
for (var key in workflow.triggers) {
const item = workflow.triggers[key]
var node = cy.getElementById(item.id)
if (node.length > 0) {
if (inside) {
node.addClass('shuffle-hover-highlight')
} else {
node.removeClass('shuffle-hover-highlight')
}
}
}
}
}
const handleActionHover = (inside, actionId) => {
var node = cy.getElementById(actionId)
if (node.length > 0) {
if (inside) {
node.addClass('shuffle-hover-highlight')
} else {
node.removeClass('shuffle-hover-highlight')
}
}
}
return (
<MenuItem key={data.name} style={{backgroundColor: inputColor, color: "white"}} value={data} onMouseOver={() => {
if (data.type === "Execution Argument") {
handleExecArgumentHover(true)
} else if (data.type === "action") {
handleActionHover(true, data.id)
}
}} onMouseOut={() => {
if (data.type === "Execution Argument") {
handleExecArgumentHover(false)
} else if (data.type === "action") {
handleActionHover(false, data.id)
}
}}>
<Tooltip color="primary" title={`Value: ${data.value}`} placement="left">
<div style={{display: "flex"}}>
{icon} {data.name}
</div>
</Tooltip>
</MenuItem>
)
})}
</Select>
</FormControl>
<ActionlistWrapper actionlist={actionlist} />
: null}
+4
View File
@@ -45,6 +45,10 @@ const inputColor = "#383B40"
export const GetParsedPaths = (inputdata, basekey) => {
const splitkey = " => "
var parsedValues = []
if (typeof(inputdata) !== "object") {
return parsedValues
}
for (const [key, value] of Object.entries(inputdata)) {
// Check if loop or JSON