Fixed Doc loading of apps, reverted header field (tbd) and fixed buttons in apps
This commit is contained in:
+10
-4
@@ -2,8 +2,14 @@
|
||||
docker pull frikky/shuffle-backend:nightly
|
||||
docker pull frikky/shuffle-frontend: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-backend:nightly ghcr.io/frikky/shuffle-backend: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 push ghcr.io/frikky/shuffle-frontend:nightly
|
||||
docker tag frikky/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:latest
|
||||
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
|
||||
|
||||
@@ -24,7 +24,7 @@ require (
|
||||
github.com/h2non/filetype v1.1.3
|
||||
github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20170819232839-0fbfe93532da // indirect
|
||||
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
|
||||
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
|
||||
google.golang.org/api v0.65.0
|
||||
|
||||
@@ -1533,7 +1533,6 @@ const ParsedAction = (props) => {
|
||||
|
||||
multiline = data.name.startsWith("${") && data.name.endsWith("}") ? true : multiline
|
||||
|
||||
console.log("Next to datafield")
|
||||
var datafield = (
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
@@ -1670,7 +1669,6 @@ const ParsedAction = (props) => {
|
||||
);
|
||||
|
||||
// Finds headers from a string to be used for autocompletion
|
||||
console.log("Before header update")
|
||||
const findHeaders = (inputdata) => {
|
||||
var splitdata = inputdata.split("\n")
|
||||
|
||||
@@ -1725,7 +1723,7 @@ const ParsedAction = (props) => {
|
||||
if (data.name.toLowerCase() === "headers") {
|
||||
//var tmpheaders = findHeaders(data.value)
|
||||
var tmpheaders = findHeaders(selectedActionParameters[count].value)
|
||||
datafield =
|
||||
const tmpdatafield =
|
||||
<div>
|
||||
{tmpheaders.map((inputdata, index) => {
|
||||
const oldkey = inputdata.key
|
||||
@@ -1862,8 +1860,6 @@ const ParsedAction = (props) => {
|
||||
</div>
|
||||
}
|
||||
|
||||
console.log("After header update")
|
||||
|
||||
//console.log("FIELD VALUE: ", data.value)
|
||||
//const regexp = new RegExp("\W+\.", "g")
|
||||
//let match
|
||||
@@ -2725,7 +2721,7 @@ const ParsedAction = (props) => {
|
||||
paddingRight: 0,
|
||||
}}
|
||||
onClick={() => {
|
||||
setAuthenticationModalOpen(true);
|
||||
setAuthenticationModalOpen(true)
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
|
||||
@@ -354,6 +354,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
const [appsLoaded, setAppsLoaded] = React.useState(false);
|
||||
const [showVideo, setShowVideo] = React.useState("");
|
||||
const [editWorkflowModalOpen, setEditWorkflowModalOpen] = React.useState(false);
|
||||
const [userediting, setUserediting] = React.useState(false)
|
||||
|
||||
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) => {
|
||||
fetch(globalUrl + "/api/v1/workflows", {
|
||||
method: "GET",
|
||||
@@ -1173,6 +1218,10 @@ const AngularWorkflow = (defaultprops) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (userediting === true) {
|
||||
useworkflow.user_editing = true
|
||||
}
|
||||
|
||||
useworkflow.actions = newActions;
|
||||
useworkflow.triggers = newTriggers;
|
||||
useworkflow.branches = newBranches;
|
||||
@@ -10814,7 +10863,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
</Tooltip>
|
||||
)}
|
||||
{/*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>
|
||||
<Button
|
||||
disabled={savingState !== 0}
|
||||
@@ -11410,6 +11459,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
onClick={() => {
|
||||
//setEditWorkflowDetails(true)
|
||||
workflow.public = false
|
||||
setUserediting(true)
|
||||
setWorkflow(workflow)
|
||||
setUpdate(Math.random());
|
||||
}}
|
||||
|
||||
@@ -1018,11 +1018,7 @@ const Apps = (props) => {
|
||||
|
||||
{activateButton}
|
||||
{editNewButton}
|
||||
{(props.userdata !== undefined &&
|
||||
(props.userdata.admin === "true" ||
|
||||
props.userdata.id === selectedApp.owner ||
|
||||
selectedApp.owner === ""
|
||||
)) || !selectedApp.generated ? (
|
||||
{(editNewButton === null && userdata !== undefined && (userdata.admin === "true" || userdata.id === selectedApp.owner || selectedApp.owner === "" )) || !selectedApp.generated ? (
|
||||
<div>
|
||||
{editButton}
|
||||
{downloadButton}
|
||||
|
||||
@@ -148,9 +148,9 @@ const GettingStarted = (props) => {
|
||||
const [downloadUrl, setDownloadUrl] = React.useState(
|
||||
"https://github.com/frikky/shuffle-workflows"
|
||||
);
|
||||
const [videoViewOpen, setVideoViewOpen] = React.useState(false)
|
||||
const [downloadBranch, setDownloadBranch] = React.useState("master");
|
||||
const [loadWorkflowsModalOpen, setLoadWorkflowsModalOpen] = React.useState(false);
|
||||
const [videoViewOpen, setVideoViewOpen] = React.useState(false);
|
||||
const [exportModalOpen, setExportModalOpen] = React.useState(false);
|
||||
const [exportData, setExportData] = React.useState("");
|
||||
|
||||
@@ -515,8 +515,6 @@ const GettingStarted = (props) => {
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
setVideoViewOpen(true)
|
||||
|
||||
if (response.status !== 200) {
|
||||
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
|
||||
setTimeout(() => {
|
||||
setFirstLoad(false)
|
||||
setVideoViewOpen(true)
|
||||
}, 100)
|
||||
} else {
|
||||
if (isLoggedIn) {
|
||||
@@ -2152,7 +2151,7 @@ const GettingStarted = (props) => {
|
||||
const steps = [
|
||||
{
|
||||
html: (
|
||||
<Typography variant={textType} style={{marginTop: textSpacingDiff}} onClick={() => {
|
||||
<Typography variant={textType} style={{marginTop: textSpacingDiff, textAlign: "left",}} onClick={() => {
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
category: "getting-started",
|
||||
@@ -2167,8 +2166,8 @@ const GettingStarted = (props) => {
|
||||
},
|
||||
{
|
||||
html:
|
||||
<Typography variant={textType} style={{marginTop: textSpacingDiff}}>
|
||||
Discover <Link to="/usecases" style={{cursor: "pointer", textDecoration: "none", color: "#f86a3e",}}>Use Case ideas</Link> and
|
||||
<Typography variant={textType} style={{marginTop: textSpacingDiff, textAlign: "left",}}>
|
||||
Discover <Link to="/welcome?tab=3" style={{cursor: "pointer", textDecoration: "none", color: "#f86a3e",}}>Use-Case ideas</Link> and
|
||||
<span style={{cursor: "pointer", textDecoration: "none", color: "#f86a3e",}} onClick={() => {
|
||||
|
||||
if (isCloud) {
|
||||
@@ -2200,7 +2199,7 @@ const GettingStarted = (props) => {
|
||||
},
|
||||
{
|
||||
html: (
|
||||
<Typography variant={textType} style={{marginTop: textSpacingDiff}} onClick={() => {
|
||||
<Typography variant={textType} style={{marginTop: textSpacingDiff, textAlign: "left",}} onClick={() => {
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
category: "getting-started",
|
||||
@@ -2218,8 +2217,8 @@ const GettingStarted = (props) => {
|
||||
},
|
||||
{
|
||||
html:
|
||||
<Typography variant={textType} style={{marginTop: textSpacingDiff}}>
|
||||
Configure your organization <Link to="/admin" style={{textDecoration: "none", color: "#f86a3e",}}>in the admin panel</Link>
|
||||
<Typography variant={textType} style={{marginTop: textSpacingDiff, textAlign: "left",}}>
|
||||
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>,
|
||||
tutorial: "configure_organization",
|
||||
}
|
||||
@@ -2227,55 +2226,53 @@ const GettingStarted = (props) => {
|
||||
|
||||
return (
|
||||
<div style={viewStyle}>
|
||||
{isCloud ?
|
||||
<Dialog
|
||||
open={videoViewOpen}
|
||||
onClose={() => {
|
||||
setVideoViewOpen(false)
|
||||
}}
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: surfaceColor,
|
||||
color: "white",
|
||||
minWidth: 560,
|
||||
minHeight: 415,
|
||||
textAlign: "center",
|
||||
},
|
||||
}}
|
||||
<Dialog
|
||||
open={videoViewOpen}
|
||||
onClose={() => {
|
||||
setVideoViewOpen(false)
|
||||
}}
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: surfaceColor,
|
||||
color: "white",
|
||||
minWidth: 560,
|
||||
minHeight: 415,
|
||||
textAlign: "center",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
Welcome to Shuffle!
|
||||
</DialogTitle>
|
||||
|
||||
<Tooltip
|
||||
title="Close window"
|
||||
placement="top"
|
||||
style={{ zIndex: 10011 }}
|
||||
>
|
||||
<DialogTitle>
|
||||
Welcome to Shuffle!
|
||||
</DialogTitle>
|
||||
|
||||
<Tooltip
|
||||
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
|
||||
<IconButton
|
||||
style={{ zIndex: 5000, position: "absolute", top: 10, right: 34 }}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setVideoViewOpen(false)
|
||||
}}
|
||||
>
|
||||
</iframe>
|
||||
</Dialog>
|
||||
: null}
|
||||
<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>
|
||||
</Dialog>
|
||||
<div style={workflowViewStyle}>
|
||||
<Typography variant="h1" style={{fontSize: 30, marginTop: 25, }}>
|
||||
Getting Started with Shuffle
|
||||
@@ -2292,8 +2289,34 @@ const GettingStarted = (props) => {
|
||||
console.log("Found tutorial for ", data.tutorial)
|
||||
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 (
|
||||
<div key={index} style={{display: "flex", marginBottom: index === steps.length-1 ? 0 : 20, }}>
|
||||
|
||||
@@ -907,48 +907,56 @@ const Workflows = (props) => {
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson !== undefined) {
|
||||
setWorkflows(responseJson);
|
||||
fetchUsecases(responseJson)
|
||||
var newarray = []
|
||||
for (var key in responseJson) {
|
||||
const wf = responseJson[key]
|
||||
if (wf.public === true) {
|
||||
continue
|
||||
}
|
||||
|
||||
newarray.push(wf)
|
||||
}
|
||||
|
||||
setWorkflows(newarray);
|
||||
fetchUsecases(newarray)
|
||||
|
||||
var setProdFilter = false
|
||||
|
||||
if (responseJson !== undefined) {
|
||||
var actionnamelist = [];
|
||||
var parsedactionlist = [];
|
||||
for (var key in responseJson) {
|
||||
const workflow = responseJson[key]
|
||||
if (workflow.status === "production") {
|
||||
setProdFilter = true
|
||||
var actionnamelist = [];
|
||||
var parsedactionlist = [];
|
||||
for (var key in newarray) {
|
||||
const workflow = newarray[key]
|
||||
if (workflow.status === "production") {
|
||||
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) {
|
||||
const action = responseJson[key].actions[actionkey];
|
||||
//console.log("Action: ", action)
|
||||
if (actionnamelist.includes(action.app_name)) {
|
||||
continue;
|
||||
}
|
||||
actionnamelist.push(action.app_name);
|
||||
parsedactionlist.push(action);
|
||||
}
|
||||
}
|
||||
|
||||
actionnamelist.push(action.app_name);
|
||||
parsedactionlist.push(action);
|
||||
}
|
||||
}
|
||||
|
||||
//console.log(parsedactionlist)
|
||||
setActionImageList(parsedactionlist);
|
||||
}
|
||||
//console.log(parsedactionlist)
|
||||
setActionImageList(parsedactionlist);
|
||||
|
||||
|
||||
if (setProdFilter === true) {
|
||||
setFilters(["status:production"]);
|
||||
const newWorkflows = responseJson.filter(workflow => workflow.status === "production")
|
||||
const newWorkflows = newarray.filter(workflow => workflow.status === "production")
|
||||
console.log(newWorkflows)
|
||||
if (newWorkflows !== undefined && newWorkflows !== null) {
|
||||
setFilteredWorkflows(newWorkflows);
|
||||
} else {
|
||||
setFilteredWorkflows(responseJson);
|
||||
setFilteredWorkflows(newarray);
|
||||
}
|
||||
} else {
|
||||
setFilteredWorkflows(responseJson);
|
||||
setFilteredWorkflows(newarray);
|
||||
}
|
||||
|
||||
// Ensures the zooming happens only once per load
|
||||
@@ -2209,6 +2217,7 @@ const Workflows = (props) => {
|
||||
width: 330,
|
||||
renderCell: (params) => {
|
||||
const data = params.row.record;
|
||||
|
||||
|
||||
return (
|
||||
<Grid item>
|
||||
|
||||
@@ -970,7 +970,7 @@ func main() {
|
||||
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
|
||||
for {
|
||||
//go getStats()
|
||||
|
||||
@@ -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 \
|
||||
--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 \
|
||||
--env ENVIRONMENT_NAME="Another env" \
|
||||
--env ORG="2e7b6a08-b63b-4fc2-bd70-718091509db1" \
|
||||
--env AUTH="env auth" \
|
||||
--env BASE_URL="https://shuffler.io" \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
ghcr.io/frikky/shuffle-orborus:nightly
|
||||
|
||||
Reference in New Issue
Block a user