Ton of minor fixes all pulled in. More info in the latest release for 1.2.0

This commit is contained in:
frikky
2023-05-15 04:42:09 +02:00
parent 70edb366a9
commit ee48543350
25 changed files with 1497 additions and 335 deletions
+8 -6
View File
@@ -145,9 +145,11 @@ const EditWorkflow = (props) => {
style: {
backgroundColor: theme.palette.surfaceColor,
color: "white",
minWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550,
maxWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550,
minWidth: isMobile ? "90%" : 550,
maxWidth: isMobile ? "90%" : 550,
minHeight: 400,
//minWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550,
//maxWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550,
},
}}
>
@@ -196,7 +198,7 @@ const EditWorkflow = (props) => {
</div>
: null}
</div>
{newWorkflow === true ?
{/*newWorkflow === true ?
<div style={{flex: 1, marginLeft: 45, }}>
<Typography variant="h6">
Use a Template
@@ -205,7 +207,7 @@ const EditWorkflow = (props) => {
Start your workflow from our templating system. This uses publied workflows from our <a href="/creators" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}}>Creators</a> to generate full Usecases or parts of your Workflow.
</Typography>
</div>
: null}
: null*/}
</div>
</DialogTitle>
<FormControl>
@@ -438,7 +440,7 @@ const EditWorkflow = (props) => {
</IconButton>
</Tooltip>
</div>
{newWorkflow === true ?
{/*newWorkflow === true ?
<div style={{marginLeft: 50, maxWidth: 400, minWidth: 400, position: "relative",}}>
<UsecaseSearch
globalUrl={globalUrl}
@@ -449,7 +451,7 @@ const EditWorkflow = (props) => {
userdata={userdata}
/>
</div>
: null}
: null*/}
</DialogContent>
<DialogActions>
<Button
+35 -12
View File
@@ -1,4 +1,5 @@
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import { useParams, useNavigate, Link } from "react-router-dom";
import { useTheme } from "@material-ui/core/styles";
import theme from '../theme';
@@ -75,6 +76,7 @@ const registeredApps = [
"jira",
"jira_service_desk",
"jira_service_management",
"github",
]
const AuthenticationOauth2 = (props) => {
@@ -92,8 +94,11 @@ const AuthenticationOauth2 = (props) => {
isCloud,
autoAuth,
authButtonOnly,
isLoggedIn,
} = props;
let navigate = useNavigate();
//const [update, setUpdate] = React.useState("|")
const [defaultConfigSet, setDefaultConfigSet] = React.useState(
authenticationType.client_id !== undefined &&
@@ -113,7 +118,7 @@ const AuthenticationOauth2 = (props) => {
const [oauthUrl, setOauthUrl] = React.useState("");
const [buttonClicked, setButtonClicked] = React.useState(false);
const [offlineAccess, setOfflineAccess] = React.useState(true);
const [offlineAccess, setOfflineAccess] = React.useState(false);
const allscopes = authenticationType.scope !== undefined ? authenticationType.scope : [];
@@ -134,8 +139,13 @@ const AuthenticationOauth2 = (props) => {
active: true,
});
useEffect(() => {
console.log("Should automatically click the auto-auth button?")
if (isLoggedIn === false) {
navigate(`/login?view=${window.location.pathname}&message=Log in to authenticate this app`)
}
console.log("Should automatically click the auto-auth button?: ", autoAuth)
if (autoAuth === true && selectedApp !== undefined) {
startOauth2Request()
}
@@ -147,7 +157,8 @@ const AuthenticationOauth2 = (props) => {
const startOauth2Request = (admin_consent) => {
// Admin consent also means to add refresh tokens
console.log("Inside oauth2 request for app: ", selectedApp.name)
selectedApp.name = selectedApp.name.replace(" ", "_").toLowerCase()
//console.log("APP: ", selectedApp)
if (selectedApp.name.toLowerCase() == "outlook_graph" || selectedApp.name.toLowerCase() == "outlook_office365") {
@@ -185,10 +196,10 @@ const AuthenticationOauth2 = (props) => {
)
} else if (selectedApp.name.toLowerCase() == "slack") {
handleOauth2Request(
"151779186901.2448678750935",
"5155508477298.5168162485601",
"",
"https://slack.com",
["chat:write:user", "im:read", "im:write", "search:read", "usergroups:read", "usergroups:write", "offline_access"],
["chat:write:user", "im:read", "im:write", "search:read", "usergroups:read", "usergroups:write",],
admin_consent,
)
} else if (selectedApp.name.toLowerCase() == "webex") {
@@ -196,7 +207,7 @@ const AuthenticationOauth2 = (props) => {
"Cab184f3d7271f540443c79b5b79845e3387abbbdb3db4233a87ea3a5432fb3d5",
"",
"https://webexapis.com",
["spark:all", "offline_access"],
["spark:all"],
admin_consent,
)
} else if (selectedApp.name.toLowerCase().includes("microsoft_teams")) {
@@ -212,7 +223,7 @@ const AuthenticationOauth2 = (props) => {
"35fa3a384040470db0c8527e90a3c2eb",
"",
"https://api.todoist.com",
["task:add", "offline_access"],
["task:add",],
admin_consent,
)
} else if (selectedApp.name.toLowerCase().includes("microsoft_sentinel")) {
@@ -220,7 +231,7 @@ const AuthenticationOauth2 = (props) => {
"4c16e8c4-3d34-4aa1-ac94-262ea170b7f7",
"",
"https://management.azure.com",
["https://management.azure.com/user_impersonation", "offline_access"],
["https://management.azure.com/user_impersonation",],
admin_consent,
)
} else if (selectedApp.name.toLowerCase().includes("microsoft_365_defender")) {
@@ -228,7 +239,7 @@ const AuthenticationOauth2 = (props) => {
"4c16e8c4-3d34-4aa1-ac94-262ea170b7f7",
"",
"https://graph.microsoft.com",
["SecurityEvents.ReadWrite.All", "offline_access"],
["SecurityEvents.ReadWrite.All",],
admin_consent,
)
} else if (selectedApp.name.toLowerCase().includes("google_sheets")) {
@@ -244,7 +255,7 @@ const AuthenticationOauth2 = (props) => {
handleOauth2Request(
"253565968129-6pij4g6ojim4gpum0h9m9u3bc357qsq7.apps.googleusercontent.com",
"",
"https://www.googleapis.com/drive/v3",
"https://www.googleapis.com",
["https://www.googleapis.com/auth/drive",],
admin_consent,
"consent",
@@ -254,9 +265,19 @@ const AuthenticationOauth2 = (props) => {
"AI02egeCQh1Zskm1QAJaaR6dzjR97V2F",
"",
"https://api.atlassian.com",
["read:jira-work", "write:jira-work", "read:servicedesk:jira-service-management", "write:servicedesk:jira-service-management", "read:request:jira-service-management", "write:request:jira-service-management", "offline_access"],
["read:jira-work", "write:jira-work", "read:servicedesk:jira-service-management", "write:servicedesk:jira-service-management", "read:request:jira-service-management", "write:request:jira-service-management",],
admin_consent,
)
} else if (selectedApp.name.toLowerCase().includes("github")) {
handleOauth2Request(
"3d272b1b782b100b1e61",
"",
"https://api.github.com",
["repo","user","project","notifications",],
admin_consent,
)
} else {
console.log("No match found for: ", selectedApp.name)
}
// write:request:jira-service-management
}
@@ -315,6 +336,7 @@ const AuthenticationOauth2 = (props) => {
}
var url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&prompt=${defaultPrompt}&scope=${resources}&state=${state}&access_type=offline`;
if (admin_consent === true) {
console.log("Running Oauth2 WITH admin consent")
//url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&prompt=consent&scope=${resources}&state=${state}&access_type=offline`;
@@ -605,7 +627,8 @@ const AuthenticationOauth2 = (props) => {
onClick={() => {
// Hardcode some stuff?
// This could prolly be added to the app itself with a "default" client ID
startOauth2Request(true)
//startOauth2Request(true)
startOauth2Request()
}}
color="primary"
>
+9 -1
View File
@@ -167,6 +167,7 @@ const ParsedAction = (props) => {
setLastSaved,
setShowVideo,
toolsAppId,
aiSubmit,
//expansionModalOpen,
//setExpansionModalOpen,
} = props;
@@ -1458,7 +1459,7 @@ const ParsedAction = (props) => {
if (found === null) {
setActivateHidingBodyButton(true);
} else {
console.log("In found: ", found, hideBody)
//console.log("In found: ", found, hideBody)
}
} else {
//console.log("SHOW BUTTON");
@@ -1532,6 +1533,12 @@ const ParsedAction = (props) => {
expansionModalOpen={expansionModalOpen}
setExpansionModalOpen={setExpansionModalOpen}
globalUrl={globalUrl}
workflowExecutions={workflowExecutions}
getParents={getParents}
selectedAction={selectedAction}
parameterName={data.name}
aiSubmit={aiSubmit}
/>
)
@@ -3222,6 +3229,7 @@ const ParsedAction = (props) => {
</Tooltip>
</div>
) : null}
{selectedAction.authentication !== undefined &&
selectedAction.authentication !== null &&
selectedAction.authentication.length > 0 ? (
+9 -5
View File
@@ -83,28 +83,32 @@ const SearchField = props => {
*/
return (
<form id="search_form" noValidate type="searchbox" action="" role="search" style={{margin: 0, }} onClick={() => {
<form id="search_form" noValidate type="searchbox" action="" role="search" style={{margin: "10px 0px 0px 0px", }} onClick={() => {
}}>
<TextField
fullWidth
style={{backgroundColor: theme.palette.inputColor, borderRadius: borderRadius, margin: 10, width: "100%",}}
style={{backgroundColor: theme.palette.surfaceColor, borderRadius: borderRadius, minWidth: 403, maxWidth: 403, }}
InputProps={{
style:{
color: "white",
fontSize: "1em",
height: 50,
margin: 0,
fontSize: "0.9em",
paddingLeft: 10,
},
startAdornment: (
disableUnderline: true,
endAdornment: (
<InputAdornment position="start">
<SearchIcon style={{marginLeft: 5}}/>
<SearchIcon style={{marginLeft: 5, color: "#f86a3e",}}/>
</InputAdornment>
),
}}
autoComplete='off'
type="search"
color="primary"
placeholder="Find Public Apps, Workflows, Documentation and more"
placeholder="Find Public Apps, Workflows, Documentation..."
value={currentRefinement}
id="shuffle_search_field"
onClick={(event) => {
+234 -8
View File
@@ -20,6 +20,7 @@ import { orange } from '@mui/material/colors';
import { isMobile } from "react-device-detect"
import NestedMenuItem from "material-ui-nested-menu-item";
import { GetParsedPaths, FindJsonPath } from "../views/Apps.jsx";
import { SetJsonDotnotation } from "../views/AngularWorkflow.jsx";
import {
FullscreenExit as FullscreenExitIcon,
@@ -114,7 +115,24 @@ const pythonFilters = [
//});
const CodeEditor = (props) => {
const { globalUrl, fieldCount, setFieldCount, actionlist, changeActionParameterCodeMirror, expansionModalOpen, setExpansionModalOpen, codedata, setcodedata, isFileEditor, runUpdateText, toolsAppId } = props
const {
globalUrl,
fieldCount,
setFieldCount,
actionlist,
changeActionParameterCodeMirror,
expansionModalOpen,
setExpansionModalOpen,
codedata,
setcodedata,
isFileEditor,
runUpdateText,
toolsAppId,
parameterName,
selectedAction ,
workflowExecutions,
getParents,
} = props
const [localcodedata, setlocalcodedata] = React.useState(codedata === undefined || codedata === null || codedata.length === 0 ? "" : codedata);
// const {codelang, setcodelang} = props
@@ -140,6 +158,8 @@ const CodeEditor = (props) => {
const [menuPosition, setMenuPosition] = useState(null);
const [showAutocomplete, setShowAutocomplete] = React.useState(false);
const [isAiLoading, setIsAiLoading] = React.useState(false);
const baseResult = ""
const [executionResult, setExecutionResult] = useState({
"valid": false,
@@ -188,8 +208,201 @@ const CodeEditor = (props) => {
setMainVariables(tmpVariables)
}, [])
const aiSubmit = (value, inputAction) => {
if (value === undefined || value === "") {
console.log("No value input!")
return
}
setIsAiLoading(true)
// Time to construct this huh... Hmm
var AppContext = []
if (inputAction !== undefined && inputAction !== null && getParents !== undefined && getParents !== null && workflowExecutions !== undefined && workflowExecutions !== null) {
const parents = getParents(inputAction)
console.log("Parents: ", parents)
var actionlist = []
if (parents.length > 1) {
for (let [key,keyval] in Object.entries(parents)) {
const item = parents[key];
if (item.label === "Execution Argument") {
continue;
}
var exampledata = item.example === undefined || item.example === null ? "" : item.example;
// Find previous execution and their variables
//exampledata === "" &&
if (workflowExecutions.length > 0) {
// Look for the ID
const found = false;
for (let [key,keyval] in Object.entries(workflowExecutions)) {
if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) {
continue;
}
var foundResult = workflowExecutions[key].results.find((result) => result.action.id === item.id);
if (foundResult === undefined || foundResult === null) {
continue;
}
if (foundResult.result !== undefined && foundResult.result !== null) {
foundResult = foundResult.result
}
const valid = validateJson(foundResult, true)
if (valid.valid) {
if (valid.result.success === false) {
//console.log("Skipping success false autocomplete")
} else {
exampledata = valid.result;
break;
}
} else {
exampledata = foundResult;
}
}
}
// 1. Take
const itemlabelComplete = item.label === null || item.label === undefined ? "" : item.label.split(" ").join("_");
const actionvalue = {
app_name: item.app_name,
action_name: item.name,
label: item.label,
type: "action",
id: item.id,
name: item.label,
autocomplete: itemlabelComplete,
example: exampledata,
};
actionlist.push(actionvalue);
}
}
var fixedResults = []
for (var i = 0; i < actionlist.length; i++) {
const item = actionlist[i];
const responseFix = SetJsonDotnotation(item.example, "")
// Check if json
const validated = validateJson(responseFix)
var exampledata = responseFix;
if (validated.valid) {
exampledata = JSON.stringify(validated.result)
}
AppContext.push({
"app_name": item.app_name,
"action_name": item.action_name,
"label": item.label,
"example": exampledata,
})
}
}
var conversationData = {
"query": value,
"output_format": "action",
"app_context": AppContext,
}
if (inputAction !== undefined) {
console.log("Add app context! This should them get parameters directly")
conversationData.output_format = "action_parameters"
conversationData.app_id = inputAction.app_id
conversationData.app_name = inputAction.app_name
conversationData.action_name = inputAction.name
conversationData.parameters = inputAction.parameters
}
fetch(`${globalUrl}/api/v1/conversation`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(conversationData),
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for stream results :O!");
}
return response.json();
})
.then((responseJson) => {
console.log("Conversation response: ", responseJson)
setIsAiLoading(false)
if (responseJson.success === false) {
if (responseJson.reason !== undefined) {
}
return
}
if (inputAction !== undefined) {
console.log("In input action! Should check params if they match, and add suggestions")
if (responseJson.parameters === undefined || responseJson.parameters.length === 0) {
return
}
for (let respParam of responseJson.parameters) {
if (respParam.name !== parameterName) {
continue
}
if (respParam.value === "") {
break
}
setlocalcodedata(respParam.value)
break
}
return
}
})
.catch((error) => {
setIsAiLoading(false)
console.log("Conv response error: ", error);
});
}
const autoFormat = (input) => {
// Check if it's default too
if (validation !== true) {
// Should try to automatically fix this input
console.log("Running AI input fixer")
if (aiSubmit !== undefined && parameterName !== undefined && selectedAction !== undefined) {
// Should remove params from selectedAction that aren't parameterName
var tmpAction = JSON.parse(JSON.stringify(selectedAction))
var tmpParams = selectedAction.parameters.filter((param) => param.name === parameterName)
var aiMsg = `Make it valid for action ${tmpAction.label} with parameter ${parameterName}: `
if (tmpParams.length > 0) {
aiMsg += tmpParams[0].value
}
if (localcodedata.startsWith("//")) {
aiMsg = localcodedata
}
tmpAction.parameters = tmpParams
console.log("Parameters: ", tmpParams.length)
aiSubmit(aiMsg, tmpAction)
}
return
}
@@ -295,6 +508,8 @@ const CodeEditor = (props) => {
var removedIndexes = 0
for (var key in itemsplit) {
var tmpitem = itemsplit[key]
// Makes sure #0 and # are same, as we only visualize first one anyway
if (tmpitem.startsWith("#")) {
removedIndexes += tmpitem.length-1
tmpitem = "#"
@@ -303,7 +518,7 @@ const CodeEditor = (props) => {
newitem.push(tmpitem)
}
//console.log("Fixed item: ", newitem, "removed length: ", removedIndexes)
console.log("Fixed item: ", newitem, "removed length: ", removedIndexes)
return newitem.join(".")
//return inputvariable
@@ -450,12 +665,17 @@ const CodeEditor = (props) => {
const found = input.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g)
console.log("FOUND: ", found)
// Whelp this is inefficient af. Single loop pls
// When the found array is empty.
if (found !== null && found !== undefined) {
try {
for (var i = 0; i < found.length; i++) {
try {
// For found specifically, should replace .#\d with .# with regex
//found[i] = found[i].toLowerCase()
const fixedVariable = fixVariable(found[i])
//var correctVariable = availableVariables.includes(fixedVariable)
@@ -468,15 +688,15 @@ const CodeEditor = (props) => {
try {
if (typeof actionlist[j].example === "object") {
input = input.replace(fixedVariable, JSON.stringify(actionlist[j].example));
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
} else if (actionlist[j].example.trim().startsWith("{") || actionlist[j].example.trim().startsWith("[")) {
input = input.replace(fixedVariable, JSON.stringify(actionlist[j].example));
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
} else {
input = input.replace(fixedVariable, actionlist[j].example)
input = input.replace(found[i], actionlist[j].example, -1)
}
} catch (e) {
input = input.replace(fixedVariable, actionlist[j].example)
input = input.replace(found[i], actionlist[j].example, -1)
}
} else {
// Couldn't find the correct example value
@@ -523,7 +743,8 @@ const CodeEditor = (props) => {
}
//console.log("FOUND2: ", fixedVariable, actionlist[j].example)
input = input.replace(fixedVariable, new_input)
input = input.replace(fixedVariable, new_input, -1)
input = input.replace(found[i], new_input, -1)
//} catch (e) {
// input = input.replace(found[i], actionlist[k].example)
@@ -769,6 +990,7 @@ const CodeEditor = (props) => {
height: 50,
width: 50,
}}
disabled={isAiLoading}
onClick={() => {
autoFormat(localcodedata)
}}
@@ -778,7 +1000,11 @@ const CodeEditor = (props) => {
title={"Auto format data"}
placement="top"
>
<AutoFixHighIcon style={{color: "rgba(255,255,255,0.7)"}}/>
{isAiLoading ?
<CircularProgress style={{height: 20, width: 20, color: "rgba(255,255,255,0.7)"}}/>
:
<AutoFixHighIcon style={{color: "rgba(255,255,255,0.7)"}}/>
}
</Tooltip>
</IconButton>
</div>