Improved app execution configuration
This commit is contained in:
@@ -2,7 +2,7 @@ module shuffle
|
|||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
//replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
|
replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
|
||||||
|
|
||||||
//replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi
|
//replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ require (
|
|||||||
github.com/Masterminds/semver v1.5.0 // indirect
|
github.com/Masterminds/semver v1.5.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||||
github.com/basgys/goxml2json v1.1.0
|
github.com/basgys/goxml2json v1.1.0
|
||||||
|
github.com/bradfitz/slice v0.0.0-20180809154707-2b758aa73013 // indirect
|
||||||
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82
|
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82
|
||||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||||
github.com/docker/docker v1.13.1
|
github.com/docker/docker v1.13.1
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU
|
|||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw=
|
github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw=
|
||||||
github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw=
|
github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw=
|
||||||
|
github.com/bradfitz/slice v0.0.0-20180809154707-2b758aa73013 h1:/P9/RL0xgWE+ehnCUUN5h3RpG3dmoMCOONO1CCvq23Y=
|
||||||
|
github.com/bradfitz/slice v0.0.0-20180809154707-2b758aa73013/go.mod h1:pccXHIvs3TV/TUqSNyEvF99sxjX2r4FFRIyw6TZY9+w=
|
||||||
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82 h1:9bAydALqAjBfPHd/eAiJBHnMZUYov8m2PkXVr+YGQeI=
|
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82 h1:9bAydALqAjBfPHd/eAiJBHnMZUYov8m2PkXVr+YGQeI=
|
||||||
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82/go.mod h1:tyA14J0sA3Hph4dt+AfCjPrYR13+vVodshQSM7km9qw=
|
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82/go.mod h1:tyA14J0sA3Hph4dt+AfCjPrYR13+vVodshQSM7km9qw=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
|||||||
@@ -5208,9 +5208,14 @@ func runInit(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fixing workflows to have real activeorg IDs
|
// Fixing workflows to have real activeorg IDs
|
||||||
|
//workflowQ := datastore.NewQuery("workflow")
|
||||||
|
//ret, err := dbclient.GetAll(ctx, workflowQ, &workflows)
|
||||||
|
//log.Printf("[INFO] Found %d workflows during startup", workflowCount)
|
||||||
|
//log.Printf("%#v, %s", ret, err)
|
||||||
|
|
||||||
|
var workflows []shuffle.Workflow
|
||||||
if len(activeOrgs) == 1 {
|
if len(activeOrgs) == 1 {
|
||||||
q := datastore.NewQuery("workflow").Limit(35)
|
q := datastore.NewQuery("workflow").Limit(35)
|
||||||
var workflows []shuffle.Workflow
|
|
||||||
_, err = dbclient.GetAll(ctx, q, &workflows)
|
_, err = dbclient.GetAll(ctx, q, &workflows)
|
||||||
if err != nil && len(workflows) == 0 {
|
if err != nil && len(workflows) == 0 {
|
||||||
log.Printf("Error getting workflows in runinit: %s", err)
|
log.Printf("Error getting workflows in runinit: %s", err)
|
||||||
|
|||||||
+3
-1
@@ -1,7 +1,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
frontend:
|
frontend:
|
||||||
#build: ./frontend
|
build: ./frontend
|
||||||
image: ghcr.io/frikky/shuffle-frontend:0.8.74
|
image: ghcr.io/frikky/shuffle-frontend:0.8.74
|
||||||
container_name: shuffle-frontend
|
container_name: shuffle-frontend
|
||||||
hostname: shuffle-frontend
|
hostname: shuffle-frontend
|
||||||
@@ -79,6 +79,8 @@ services:
|
|||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
networks:
|
networks:
|
||||||
- shuffle
|
- shuffle
|
||||||
|
environment:
|
||||||
|
- _JAVA_OPTIONS="-Xmx2g"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- ${DB_LOCATION}:/etc/shuffle
|
- ${DB_LOCATION}:/etc/shuffle
|
||||||
|
|||||||
@@ -546,6 +546,10 @@ const ParsedAction = (props) => {
|
|||||||
var disabled = false
|
var disabled = false
|
||||||
var rows = "5"
|
var rows = "5"
|
||||||
var openApiHelperText = "This is an OpenAPI specific field"
|
var openApiHelperText = "This is an OpenAPI specific field"
|
||||||
|
if (selectedApp.generated && data.name === "url" && data.required && data.configuration && hideExtraTypes) {
|
||||||
|
console.log("GENERATED WITH DATA: ", data)
|
||||||
|
return null
|
||||||
|
}
|
||||||
if (selectedApp.generated && data.name === "body") {
|
if (selectedApp.generated && data.name === "body") {
|
||||||
const regex = /\${(\w+)}/g
|
const regex = /\${(\w+)}/g
|
||||||
const found = placeholder.match(regex)
|
const found = placeholder.match(regex)
|
||||||
|
|||||||
@@ -688,6 +688,13 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
const saveWorkflow = (curworkflow) => {
|
const saveWorkflow = (curworkflow) => {
|
||||||
var success = false
|
var success = false
|
||||||
|
|
||||||
|
if (isCloud && !isLoggedIn) {
|
||||||
|
console.log("Should redirect to register with redirect.")
|
||||||
|
window.location.href = `/register?view=/workflows/${props.match.params.key}&message=You need sign up to use workflows with Shuffle`
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
setSavingState(2)
|
setSavingState(2)
|
||||||
|
|
||||||
// This might not be the right course of action, but seems logical, as items could be running already
|
// This might not be the right course of action, but seems logical, as items could be running already
|
||||||
@@ -1163,7 +1170,7 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
if (responseJson.public) {
|
if (responseJson.public) {
|
||||||
alert.info("This workflow is public. You will have to save it to make it your own!")
|
alert.info("This workflow is public. You will have to save it to make it your own!")
|
||||||
setLastSaved(false)
|
//setLastSaved(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
setWorkflow(responseJson)
|
setWorkflow(responseJson)
|
||||||
@@ -1267,8 +1274,9 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
// Comparing locations between nodes and setting views
|
// Comparing locations between nodes and setting views
|
||||||
const onNodeDrag = (event) => {
|
const onNodeDrag = (event) => {
|
||||||
//console.log("DRAGGING: ", event.target)
|
if (Object.getOwnPropertyNames(selectedAction).length === 0) {
|
||||||
//console.log("LEN2: ", event.target.edges.length)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const nodedata = event.target.data()
|
const nodedata = event.target.data()
|
||||||
if (nodedata.app_name == "Shuffle Tools" || nodedata.app_name == "Testing") {
|
if (nodedata.app_name == "Shuffle Tools" || nodedata.app_name == "Testing") {
|
||||||
@@ -1281,6 +1289,12 @@ const AngularWorkflow = (props) => {
|
|||||||
// 3. If it is, then hide text
|
// 3. If it is, then hide text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(nodedata)
|
||||||
|
var x = event.clientX, y = event.clientY,
|
||||||
|
elementMouseIsOver = document.elementFromPoint(x, y)
|
||||||
|
console.log("ELEMENT: ", elementMouseIsOver)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
event.target.animate({
|
event.target.animate({
|
||||||
@@ -2952,10 +2966,11 @@ const AngularWorkflow = (props) => {
|
|||||||
id="appsearch"
|
id="appsearch"
|
||||||
onKeyPress={(event) => {
|
onKeyPress={(event) => {
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
runSearch(event.target.value)
|
event.target.blur(event)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onBlur={(event) => {
|
onBlur={(event) => {
|
||||||
|
console.log("BLUR: ", event.target.value)
|
||||||
runSearch(event.target.value)
|
runSearch(event.target.value)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -2972,12 +2987,19 @@ const AngularWorkflow = (props) => {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div style={{textAlign: "center", width: leftBarSize}}>
|
apps.length > 0 ?
|
||||||
<CircularProgress style={{marginTop: 25, height: 35, width: 35, marginLeft: "auto", marginRight: "auto", }} />
|
<div style={{textAlign: "center", width: leftBarSize, marginTop: 10, }}>
|
||||||
<Typography variant="body1" color="textSecondary">
|
<Typography variant="body1" color="textSecondary">
|
||||||
Loading apps
|
Couldn't find app. Is it active?
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
|
:
|
||||||
|
<div style={{textAlign: "center", width: leftBarSize}}>
|
||||||
|
<CircularProgress style={{marginTop: 25, height: 35, width: 35, marginLeft: "auto", marginRight: "auto", }} />
|
||||||
|
<Typography variant="body1" color="textSecondary">
|
||||||
|
Loading apps
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -5385,25 +5407,27 @@ const AngularWorkflow = (props) => {
|
|||||||
<div style={bottomBarStyle}>
|
<div style={bottomBarStyle}>
|
||||||
{executionButton}
|
{executionButton}
|
||||||
<div style={{marginLeft: "10px", left: boxSize, bottom: 0, position: "absolute"}}>
|
<div style={{marginLeft: "10px", left: boxSize, bottom: 0, position: "absolute"}}>
|
||||||
<Tooltip color="primary" title="An argument to be used for execution. This is a variable available to every node in your workflow." placement="top">
|
{workflow.public ? null :
|
||||||
<TextField
|
<Tooltip color="primary" title="An argument to be used for execution. This is a variable available to every node in your workflow." placement="top">
|
||||||
id="execution_argument_input_field"
|
<TextField
|
||||||
style={theme.palette.textFieldStyle}
|
id="execution_argument_input_field"
|
||||||
disabled={workflow.public}
|
style={theme.palette.textFieldStyle}
|
||||||
InputProps={{
|
disabled={workflow.public}
|
||||||
style: theme.palette.innerTextfieldStyle,
|
InputProps={{
|
||||||
}}
|
style: theme.palette.innerTextfieldStyle,
|
||||||
color="secondary"
|
}}
|
||||||
placeholder={"Execution Argument"}
|
color="secondary"
|
||||||
defaultValue={executionText}
|
placeholder={"Execution Argument"}
|
||||||
onBlur={(e) => {
|
defaultValue={executionText}
|
||||||
setExecutionText(e.target.value)
|
onBlur={(e) => {
|
||||||
}}
|
setExecutionText(e.target.value)
|
||||||
/>
|
}}
|
||||||
</Tooltip>
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
<Tooltip color="primary" title="Save (ctrl+s)" placement="top">
|
<Tooltip color="primary" title="Save (ctrl+s)" placement="top">
|
||||||
<span>
|
<span>
|
||||||
<Button disabled={savingState !== 0} color="primary" style={{height: 50, width: 64, marginLeft: 10, }} variant={lastSaved ? "outlined" : "contained"} onClick={() => saveWorkflow()}>
|
<Button disabled={savingState !== 0} color="primary" style={{height: workflow.public ? 100 : 50, width: workflow.public ? 100 : 64, marginLeft: 10, }} variant={lastSaved && !(workflow.public) ? "outlined" : "contained"} onClick={() => saveWorkflow()}>
|
||||||
{savingState === 2 ? <CircularProgress style={{height: 35, width: 35}} /> : savingState === 1 ? <DoneIcon style={{color: green}} /> : <SaveIcon /> }
|
{savingState === 2 ? <CircularProgress style={{height: 35, width: 35}} /> : savingState === 1 ? <DoneIcon style={{color: green}} /> : <SaveIcon /> }
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
@@ -5411,7 +5435,7 @@ const AngularWorkflow = (props) => {
|
|||||||
{workflow.public ?
|
{workflow.public ?
|
||||||
<Tooltip color="secondary" title="Download workflow" placement="top-start">
|
<Tooltip color="secondary" title="Download workflow" placement="top-start">
|
||||||
<span>
|
<span>
|
||||||
<Button color="primary" style={{height: 50, marginLeft: 10, }} variant="contained" onClick={() => {
|
<Button color="primary" style={{height: 50, marginLeft: 10, }} variant="outlined" onClick={() => {
|
||||||
//setExecutionModalOpen(true)
|
//setExecutionModalOpen(true)
|
||||||
//getWorkflowExecution(props.match.params.key, "")
|
//getWorkflowExecution(props.match.params.key, "")
|
||||||
//data = sanitizeWorkflow(workflow)
|
//data = sanitizeWorkflow(workflow)
|
||||||
@@ -6519,10 +6543,16 @@ const AngularWorkflow = (props) => {
|
|||||||
//return
|
//return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Automatically mapping fields that already exist (predefined).
|
||||||
|
// Warning if fields are NOT filled
|
||||||
for (var key in selectedApp.authentication.parameters) {
|
for (var key in selectedApp.authentication.parameters) {
|
||||||
if (authenticationOption.fields[selectedApp.authentication.parameters[key].name].length === 0) {
|
if (authenticationOption.fields[selectedApp.authentication.parameters[key].name].length === 0) {
|
||||||
alert.info("Field "+selectedApp.authentication.parameters[key].name+" can't be empty")
|
if (selectedApp.authentication.parameters[key].value !== undefined && selectedApp.authentication.parameters[key].value !== null && selectedApp.authentication.parameters[key].value.length > 0) {
|
||||||
return
|
authenticationOption.fields[selectedApp.authentication.parameters[key].name] = selectedApp.authentication.parameters[key].value
|
||||||
|
} else {
|
||||||
|
alert.info("Field "+selectedApp.authentication.parameters[key].name+" can't be empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6597,8 +6627,8 @@ const AngularWorkflow = (props) => {
|
|||||||
authenticationOption.label = event.target.value
|
authenticationOption.label = event.target.value
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{selectedApp.link.length > 0 ? <div style={{marginTop: 15}}><EndpointData /></div> : null}
|
|
||||||
<Divider style={{marginTop: 15, marginBottom: 15, backgroundColor: "rgb(91, 96, 100)"}}/>
|
<Divider style={{marginTop: 15, marginBottom: 15, backgroundColor: "rgb(91, 96, 100)"}}/>
|
||||||
|
{/*selectedApp.link.length > 0 ? <div style={{marginTop: 15}}><EndpointData /></div> : null*/}
|
||||||
<div style={{}}/>
|
<div style={{}}/>
|
||||||
{selectedApp.authentication.parameters.map((data, index) => {
|
{selectedApp.authentication.parameters.map((data, index) => {
|
||||||
return (
|
return (
|
||||||
@@ -6619,6 +6649,7 @@ const AngularWorkflow = (props) => {
|
|||||||
fullWidth
|
fullWidth
|
||||||
type={data.example !== undefined && data.example.includes("***") ? "password" : "text"}
|
type={data.example !== undefined && data.example.includes("***") ? "password" : "text"}
|
||||||
color="primary"
|
color="primary"
|
||||||
|
defaultValue={data.value !== undefined && data.value !== null ? data.value : ""}
|
||||||
placeholder={data.example}
|
placeholder={data.example}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
authenticationOption.fields[data.name] = event.target.value
|
authenticationOption.fields[data.name] = event.target.value
|
||||||
@@ -6664,7 +6695,6 @@ const AngularWorkflow = (props) => {
|
|||||||
fullWidth
|
fullWidth
|
||||||
type="text"
|
type="text"
|
||||||
color="primary"
|
color="primary"
|
||||||
disabled={true}
|
|
||||||
placeholder="Bearer token"
|
placeholder="Bearer token"
|
||||||
defaultValue={selectedApp.link}
|
defaultValue={selectedApp.link}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
|
|||||||
@@ -1994,7 +1994,7 @@ const AppCreator = (props) => {
|
|||||||
setUpdate(Math.random())
|
setUpdate(Math.random())
|
||||||
} else if (parsedurl.startsWith("curl")) {
|
} else if (parsedurl.startsWith("curl")) {
|
||||||
const request = parseCurl(event.target.value)
|
const request = parseCurl(event.target.value)
|
||||||
if (request !== event.target.value) {
|
if (request !== event.target.value && request.method !== undefined && request.method !== null) {
|
||||||
if (request.method.toUpperCase() !== currentAction.Method) {
|
if (request.method.toUpperCase() !== currentAction.Method) {
|
||||||
setCurrentActionMethod(request.method.toUpperCase())
|
setCurrentActionMethod(request.method.toUpperCase())
|
||||||
setActionField("method", request.method.toUpperCase())
|
setActionField("method", request.method.toUpperCase())
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ const LoginDialog = props => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsLoggedIn(true)
|
setIsLoggedIn(true)
|
||||||
|
|
||||||
window.location.pathname = "/workflows"
|
window.location.pathname = "/workflows"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -658,7 +658,7 @@ const Workflows = (props) => {
|
|||||||
const exportWorkflow = (data) => {
|
const exportWorkflow = (data) => {
|
||||||
let exportFileDefaultName = data.name+'.json';
|
let exportFileDefaultName = data.name+'.json';
|
||||||
data = sanitizeWorkflow(data)
|
data = sanitizeWorkflow(data)
|
||||||
return
|
//return
|
||||||
|
|
||||||
// Add correct ID's for triggers
|
// Add correct ID's for triggers
|
||||||
// Add mag
|
// Add mag
|
||||||
|
|||||||
Reference in New Issue
Block a user