Fixed Doc loading of apps, reverted header field (tbd) and fixed buttons in apps

This commit is contained in:
frikky
2022-07-27 01:00:27 +02:00
parent 4c047e457c
commit 6b07581ce3
9 changed files with 196 additions and 107 deletions
+10 -4
View File
@@ -2,8 +2,14 @@
docker pull frikky/shuffle-backend:nightly docker pull frikky/shuffle-backend:nightly
docker pull frikky/shuffle-frontend:nightly docker pull frikky/shuffle-frontend:nightly
docker tag frikky/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:nightly #docker tag frikky/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:nightly
docker tag frikky/shuffle-frontend:nightly ghcr.io/frikky/shuffle-frontend:nightly #docker tag frikky/shuffle-frontend:nightly ghcr.io/frikky/shuffle-frontend:nightly
#
#docker push ghcr.io/frikky/shuffle-backend:nightly
#docker push ghcr.io/frikky/shuffle-frontend:nightly
docker push ghcr.io/frikky/shuffle-backend:nightly docker tag frikky/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:latest
docker push ghcr.io/frikky/shuffle-frontend:nightly docker tag frikky/shuffle-frontend:nightly ghcr.io/frikky/shuffle-frontend:latest
docker push ghcr.io/frikky/shuffle-backend:latest
docker push ghcr.io/frikky/shuffle-frontend:latest
+1 -1
View File
@@ -24,7 +24,7 @@ require (
github.com/h2non/filetype v1.1.3 github.com/h2non/filetype v1.1.3
github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20170819232839-0fbfe93532da // indirect github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20170819232839-0fbfe93532da // indirect
github.com/satori/go.uuid v1.2.0 github.com/satori/go.uuid v1.2.0
github.com/shuffle/shuffle-shared v0.2.69 github.com/shuffle/shuffle-shared v0.2.72
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
google.golang.org/api v0.65.0 google.golang.org/api v0.65.0
+2 -6
View File
@@ -1533,7 +1533,6 @@ const ParsedAction = (props) => {
multiline = data.name.startsWith("${") && data.name.endsWith("}") ? true : multiline multiline = data.name.startsWith("${") && data.name.endsWith("}") ? true : multiline
console.log("Next to datafield")
var datafield = ( var datafield = (
<TextField <TextField
disabled={disabled} disabled={disabled}
@@ -1670,7 +1669,6 @@ const ParsedAction = (props) => {
); );
// Finds headers from a string to be used for autocompletion // Finds headers from a string to be used for autocompletion
console.log("Before header update")
const findHeaders = (inputdata) => { const findHeaders = (inputdata) => {
var splitdata = inputdata.split("\n") var splitdata = inputdata.split("\n")
@@ -1725,7 +1723,7 @@ const ParsedAction = (props) => {
if (data.name.toLowerCase() === "headers") { if (data.name.toLowerCase() === "headers") {
//var tmpheaders = findHeaders(data.value) //var tmpheaders = findHeaders(data.value)
var tmpheaders = findHeaders(selectedActionParameters[count].value) var tmpheaders = findHeaders(selectedActionParameters[count].value)
datafield = const tmpdatafield =
<div> <div>
{tmpheaders.map((inputdata, index) => { {tmpheaders.map((inputdata, index) => {
const oldkey = inputdata.key const oldkey = inputdata.key
@@ -1862,8 +1860,6 @@ const ParsedAction = (props) => {
</div> </div>
} }
console.log("After header update")
//console.log("FIELD VALUE: ", data.value) //console.log("FIELD VALUE: ", data.value)
//const regexp = new RegExp("\W+\.", "g") //const regexp = new RegExp("\W+\.", "g")
//let match //let match
@@ -2725,7 +2721,7 @@ const ParsedAction = (props) => {
paddingRight: 0, paddingRight: 0,
}} }}
onClick={() => { onClick={() => {
setAuthenticationModalOpen(true); setAuthenticationModalOpen(true)
}} }}
> >
<Tooltip <Tooltip
+51 -1
View File
@@ -354,6 +354,7 @@ const AngularWorkflow = (defaultprops) => {
const [appsLoaded, setAppsLoaded] = React.useState(false); const [appsLoaded, setAppsLoaded] = React.useState(false);
const [showVideo, setShowVideo] = React.useState(""); const [showVideo, setShowVideo] = React.useState("");
const [editWorkflowModalOpen, setEditWorkflowModalOpen] = React.useState(false); const [editWorkflowModalOpen, setEditWorkflowModalOpen] = React.useState(false);
const [userediting, setUserediting] = React.useState(false)
const [lastSaved, setLastSaved] = React.useState(true); const [lastSaved, setLastSaved] = React.useState(true);
@@ -392,6 +393,50 @@ const AngularWorkflow = (defaultprops) => {
}, },
}); });
const getAppDocs = (appname) => {
fetch(`${globalUrl}/api/v1/docs/${appname}?location=openapi`, {
headers: {
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status === 200) {
//alert.success("Successfully GOT app "+appId)
} else {
//alert.error("Failed getting app");
}
return response.json();
})
.then((responseJson) => {
if (responseJson.success === true) {
console.log("RESPONSE FOR APP: ", responseJson.reason);
if (responseJson.reason !== undefined && responseJson.reason !== undefined && responseJson.reason.length > 0) {
selectedApp.documentation = responseJson.reason
setSelectedApp(selectedApp)
setUpdate(Math.random())
}
}
})
.catch((error) => {
alert.error(error.toString());
});
};
useEffect(() => {
if (authenticationModalOpen === true && selectedAction.app_name !== undefined) {
console.log(`Should get app docs for: ${selectedAction.app_name}`)
if (selectedAction.documentation === undefined || selectedAction.documentation === null || selectedAction.documentation.length === 0) {
// SelectedApp.documentation = Markdown? If so, it works
getAppDocs(selectedAction.app_name)
}
}
}, [authenticationModalOpen])
const getAvailableWorkflows = (trigger_index) => { const getAvailableWorkflows = (trigger_index) => {
fetch(globalUrl + "/api/v1/workflows", { fetch(globalUrl + "/api/v1/workflows", {
method: "GET", method: "GET",
@@ -1173,6 +1218,10 @@ const AngularWorkflow = (defaultprops) => {
} }
} }
if (userediting === true) {
useworkflow.user_editing = true
}
useworkflow.actions = newActions; useworkflow.actions = newActions;
useworkflow.triggers = newTriggers; useworkflow.triggers = newTriggers;
useworkflow.branches = newBranches; useworkflow.branches = newBranches;
@@ -10814,7 +10863,7 @@ const AngularWorkflow = (defaultprops) => {
</Tooltip> </Tooltip>
)} )}
{/*userdata.avatar === creatorProfile.github_avatar ? null :*/} {/*userdata.avatar === creatorProfile.github_avatar ? null :*/}
<Tooltip color="primary" title="Save Workflow" placement="top"> <Tooltip color="primary" title={workflow.public === true ? "Use this Workflow in your organization" : "Save Workflow"} placement="top">
<span> <span>
<Button <Button
disabled={savingState !== 0} disabled={savingState !== 0}
@@ -11410,6 +11459,7 @@ const AngularWorkflow = (defaultprops) => {
onClick={() => { onClick={() => {
//setEditWorkflowDetails(true) //setEditWorkflowDetails(true)
workflow.public = false workflow.public = false
setUserediting(true)
setWorkflow(workflow) setWorkflow(workflow)
setUpdate(Math.random()); setUpdate(Math.random());
}} }}
+1 -5
View File
@@ -1018,11 +1018,7 @@ const Apps = (props) => {
{activateButton} {activateButton}
{editNewButton} {editNewButton}
{(props.userdata !== undefined && {(editNewButton === null && userdata !== undefined && (userdata.admin === "true" || userdata.id === selectedApp.owner || selectedApp.owner === "" )) || !selectedApp.generated ? (
(props.userdata.admin === "true" ||
props.userdata.id === selectedApp.owner ||
selectedApp.owner === ""
)) || !selectedApp.generated ? (
<div> <div>
{editButton} {editButton}
{downloadButton} {downloadButton}
+80 -57
View File
@@ -148,9 +148,9 @@ const GettingStarted = (props) => {
const [downloadUrl, setDownloadUrl] = React.useState( const [downloadUrl, setDownloadUrl] = React.useState(
"https://github.com/frikky/shuffle-workflows" "https://github.com/frikky/shuffle-workflows"
); );
const [videoViewOpen, setVideoViewOpen] = React.useState(false)
const [downloadBranch, setDownloadBranch] = React.useState("master"); const [downloadBranch, setDownloadBranch] = React.useState("master");
const [loadWorkflowsModalOpen, setLoadWorkflowsModalOpen] = React.useState(false); const [loadWorkflowsModalOpen, setLoadWorkflowsModalOpen] = React.useState(false);
const [videoViewOpen, setVideoViewOpen] = React.useState(false);
const [exportModalOpen, setExportModalOpen] = React.useState(false); const [exportModalOpen, setExportModalOpen] = React.useState(false);
const [exportData, setExportData] = React.useState(""); const [exportData, setExportData] = React.useState("");
@@ -515,8 +515,6 @@ const GettingStarted = (props) => {
credentials: "include", credentials: "include",
}) })
.then((response) => { .then((response) => {
setVideoViewOpen(true)
if (response.status !== 200) { if (response.status !== 200) {
console.log("Status not 200 for workflows :O!: ", response.status); console.log("Status not 200 for workflows :O!: ", response.status);
@@ -561,6 +559,7 @@ const GettingStarted = (props) => {
// Ensures the zooming happens only once per load // Ensures the zooming happens only once per load
setTimeout(() => { setTimeout(() => {
setFirstLoad(false) setFirstLoad(false)
setVideoViewOpen(true)
}, 100) }, 100)
} else { } else {
if (isLoggedIn) { if (isLoggedIn) {
@@ -2152,7 +2151,7 @@ const GettingStarted = (props) => {
const steps = [ const steps = [
{ {
html: ( html: (
<Typography variant={textType} style={{marginTop: textSpacingDiff}} onClick={() => { <Typography variant={textType} style={{marginTop: textSpacingDiff, textAlign: "left",}} onClick={() => {
if (isCloud) { if (isCloud) {
ReactGA.event({ ReactGA.event({
category: "getting-started", category: "getting-started",
@@ -2167,8 +2166,8 @@ const GettingStarted = (props) => {
}, },
{ {
html: html:
<Typography variant={textType} style={{marginTop: textSpacingDiff}}> <Typography variant={textType} style={{marginTop: textSpacingDiff, textAlign: "left",}}>
Discover <Link to="/usecases" style={{cursor: "pointer", textDecoration: "none", color: "#f86a3e",}}>Use Case ideas</Link> and&nbsp; Discover <Link to="/welcome?tab=3" style={{cursor: "pointer", textDecoration: "none", color: "#f86a3e",}}>Use-Case ideas</Link> and&nbsp;
<span style={{cursor: "pointer", textDecoration: "none", color: "#f86a3e",}} onClick={() => { <span style={{cursor: "pointer", textDecoration: "none", color: "#f86a3e",}} onClick={() => {
if (isCloud) { if (isCloud) {
@@ -2200,7 +2199,7 @@ const GettingStarted = (props) => {
}, },
{ {
html: ( html: (
<Typography variant={textType} style={{marginTop: textSpacingDiff}} onClick={() => { <Typography variant={textType} style={{marginTop: textSpacingDiff, textAlign: "left",}} onClick={() => {
if (isCloud) { if (isCloud) {
ReactGA.event({ ReactGA.event({
category: "getting-started", category: "getting-started",
@@ -2218,8 +2217,8 @@ const GettingStarted = (props) => {
}, },
{ {
html: html:
<Typography variant={textType} style={{marginTop: textSpacingDiff}}> <Typography variant={textType} style={{marginTop: textSpacingDiff, textAlign: "left",}}>
Configure your organization <Link to="/admin" style={{textDecoration: "none", color: "#f86a3e",}}>in the admin panel</Link> Configure your organization name <Link to="/admin" style={{textDecoration: "none", color: "#f86a3e",}}>in the admin panel</Link> and <Link to="/admin?tab=users" style={{textDecoration: "none", color: "#f86a3e",}}>invite your team</Link>
</Typography>, </Typography>,
tutorial: "configure_organization", tutorial: "configure_organization",
} }
@@ -2227,55 +2226,53 @@ const GettingStarted = (props) => {
return ( return (
<div style={viewStyle}> <div style={viewStyle}>
{isCloud ? <Dialog
<Dialog open={videoViewOpen}
open={videoViewOpen} onClose={() => {
onClose={() => { setVideoViewOpen(false)
setVideoViewOpen(false) }}
}} PaperProps={{
PaperProps={{ style: {
style: { backgroundColor: surfaceColor,
backgroundColor: surfaceColor, color: "white",
color: "white", minWidth: 560,
minWidth: 560, minHeight: 415,
minHeight: 415, textAlign: "center",
textAlign: "center", },
}, }}
}} >
<DialogTitle>
Welcome to Shuffle!
</DialogTitle>
<Tooltip
title="Close window"
placement="top"
style={{ zIndex: 10011 }}
> >
<DialogTitle> <IconButton
Welcome to Shuffle! style={{ zIndex: 5000, position: "absolute", top: 10, right: 34 }}
</DialogTitle> onClick={(e) => {
e.preventDefault();
<Tooltip setVideoViewOpen(false)
title="Close window" }}
placement="top"
style={{ zIndex: 10011 }}
>
<IconButton
style={{ zIndex: 5000, position: "absolute", top: 10, right: 34 }}
onClick={(e) => {
e.preventDefault();
setVideoViewOpen(false)
}}
>
<CloseIcon style={{ color: "white" }} />
</IconButton>
</Tooltip>
<iframe
width="560"
height="315"
style={{margin: "0px auto 0px auto", width: 560, height: 315,}}
src="https://www.youtube-nocookie.com/embed/rO7k9q3OgC0"
title="Introduction video"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
> >
</iframe> <CloseIcon style={{ color: "white" }} />
</Dialog> </IconButton>
: null} </Tooltip>
<iframe
width="560"
height="315"
style={{margin: "0px auto 0px auto", width: 560, height: 315,}}
src="https://www.youtube-nocookie.com/embed/rO7k9q3OgC0"
title="Introduction video"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
>
</iframe>
</Dialog>
<div style={workflowViewStyle}> <div style={workflowViewStyle}>
<Typography variant="h1" style={{fontSize: 30, marginTop: 25, }}> <Typography variant="h1" style={{fontSize: 30, marginTop: 25, }}>
Getting Started with Shuffle Getting Started with Shuffle
@@ -2292,8 +2289,34 @@ const GettingStarted = (props) => {
console.log("Found tutorial for ", data.tutorial) console.log("Found tutorial for ", data.tutorial)
tutorialFound = true tutorialFound = true
} }
}
if (tutorialFound === false) {
if (data.tutorial === "discover_workflows") {
if (workflows.length > 0) {
for (var key in workflows) {
const tmpworkflow = workflows[key]
if (tmpworkflow.published_id !== undefined && tmpworkflow.published_id !== null && tmpworkflow.published_id.length > 0) {
tutorialFound = true
break
}
}
}
}
if (data.tutorial === "learn_shuffle") {
//tutorial: "discover_workflows",
if (workflows.length > 0) {
tutorialFound = true
}
}
if (data.tutorial === "configure_organization") {
if (userdata.active_org.name !== userdata.username) {
tutorialFound = true
}
}
}
}
return ( return (
<div key={index} style={{display: "flex", marginBottom: index === steps.length-1 ? 0 : 20, }}> <div key={index} style={{display: "flex", marginBottom: index === steps.length-1 ? 0 : 20, }}>
+35 -26
View File
@@ -907,48 +907,56 @@ const Workflows = (props) => {
}) })
.then((responseJson) => { .then((responseJson) => {
if (responseJson !== undefined) { if (responseJson !== undefined) {
setWorkflows(responseJson); var newarray = []
fetchUsecases(responseJson) for (var key in responseJson) {
const wf = responseJson[key]
if (wf.public === true) {
continue
}
newarray.push(wf)
}
setWorkflows(newarray);
fetchUsecases(newarray)
var setProdFilter = false var setProdFilter = false
if (responseJson !== undefined) { var actionnamelist = [];
var actionnamelist = []; var parsedactionlist = [];
var parsedactionlist = []; for (var key in newarray) {
for (var key in responseJson) { const workflow = newarray[key]
const workflow = responseJson[key] if (workflow.status === "production") {
if (workflow.status === "production") { setProdFilter = true
setProdFilter = true }
for (var actionkey in newarray[key].actions) {
const action = newarray[key].actions[actionkey];
//console.log("Action: ", action)
if (actionnamelist.includes(action.app_name)) {
continue;
} }
for (var actionkey in responseJson[key].actions) { actionnamelist.push(action.app_name);
const action = responseJson[key].actions[actionkey]; parsedactionlist.push(action);
//console.log("Action: ", action) }
if (actionnamelist.includes(action.app_name)) { }
continue;
}
actionnamelist.push(action.app_name); //console.log(parsedactionlist)
parsedactionlist.push(action); setActionImageList(parsedactionlist);
}
}
//console.log(parsedactionlist)
setActionImageList(parsedactionlist);
}
if (setProdFilter === true) { if (setProdFilter === true) {
setFilters(["status:production"]); setFilters(["status:production"]);
const newWorkflows = responseJson.filter(workflow => workflow.status === "production") const newWorkflows = newarray.filter(workflow => workflow.status === "production")
console.log(newWorkflows) console.log(newWorkflows)
if (newWorkflows !== undefined && newWorkflows !== null) { if (newWorkflows !== undefined && newWorkflows !== null) {
setFilteredWorkflows(newWorkflows); setFilteredWorkflows(newWorkflows);
} else { } else {
setFilteredWorkflows(responseJson); setFilteredWorkflows(newarray);
} }
} else { } else {
setFilteredWorkflows(responseJson); setFilteredWorkflows(newarray);
} }
// Ensures the zooming happens only once per load // Ensures the zooming happens only once per load
@@ -2209,6 +2217,7 @@ const Workflows = (props) => {
width: 330, width: 330,
renderCell: (params) => { renderCell: (params) => {
const data = params.row.record; const data = params.row.record;
return ( return (
<Grid item> <Grid item>
+1 -1
View File
@@ -970,7 +970,7 @@ func main() {
req.Header.Add("Org", org) req.Header.Add("Org", org)
} }
log.Printf("[INFO] Waiting for executions at %s with Environment %s", fullUrl, environment) log.Printf("[INFO] Waiting for executions at %s with Environment %#v", fullUrl, environment)
hasStarted := false hasStarted := false
for { for {
//go getStats() //go getStats()
+15 -6
View File
@@ -1,10 +1,19 @@
#docker run \
# --env DOCKER_API_VERSION=1.40 \
# --env ENVIRONMENT_NAME="Shuffle" \
# --env BASE_URL="http://192.168.86.45:5001" \
# --env HTTP_PROXY="http://192.168.86.45:8082" \
# --env HTTPS_PROXY="https://192.168.86.45:8082" \
# --env SHUFFLE_PASS_WORKER_PROXY=true \
# --env SHUFFLE_PASS_APP_PROXY=true \
# -v /var/run/docker.sock:/var/run/docker.sock \
# ghcr.io/frikky/shuffle-orborus:nightly
docker run \ docker run \
--env DOCKER_API_VERSION=1.40 \ --env DOCKER_API_VERSION=1.40 \
--env ENVIRONMENT_NAME="Shuffle" \ --env ENVIRONMENT_NAME="Another env" \
--env BASE_URL="http://192.168.86.45:5001" \ --env ORG="2e7b6a08-b63b-4fc2-bd70-718091509db1" \
--env HTTP_PROXY="http://192.168.86.45:8082" \ --env AUTH="env auth" \
--env HTTPS_PROXY="https://192.168.86.45:8082" \ --env BASE_URL="https://shuffler.io" \
--env SHUFFLE_PASS_WORKER_PROXY=true \
--env SHUFFLE_PASS_APP_PROXY=true \
-v /var/run/docker.sock:/var/run/docker.sock \ -v /var/run/docker.sock:/var/run/docker.sock \
ghcr.io/frikky/shuffle-orborus:nightly ghcr.io/frikky/shuffle-orborus:nightly