Added new colors and workflow view
This commit is contained in:
@@ -1543,7 +1543,7 @@ class AppBase:
|
||||
sourcevalue = condition["source"]["value"]
|
||||
check, sourcevalue, is_loop = parse_params(action, fullexecution, condition["source"])
|
||||
if check:
|
||||
return False, "Failed condition: %s %s %s because %s" % (sourcevalue, condition["condition"]["value"], destinationvalue, check)
|
||||
return False, {"success": False, "reason": "Failed condition: %s %s %s because %s" % (sourcevalue, condition["condition"]["value"], destinationvalue, check)}
|
||||
|
||||
|
||||
#sourcevalue = sourcevalue.encode("utf-8")
|
||||
@@ -1552,7 +1552,7 @@ class AppBase:
|
||||
|
||||
check, destinationvalue, is_loop = parse_params(action, fullexecution, condition["destination"])
|
||||
if check:
|
||||
return False, "Failed condition: %s %s %s because %s" % (sourcevalue, condition["condition"]["value"], destinationvalue, check)
|
||||
return False, {"success": False, "reason": "Failed condition: %s %s %s because %s" % (sourcevalue, condition["condition"]["value"], destinationvalue, check)}
|
||||
|
||||
#destinationvalue = destinationvalue.encode("utf-8")
|
||||
destinationvalue = parse_wrapper_start(destinationvalue)
|
||||
@@ -1593,7 +1593,7 @@ class AppBase:
|
||||
|
||||
if not validation:
|
||||
self.logger.info("Failed condition check for %s %s %s." % (sourcevalue, condition["condition"]["value"], destinationvalue))
|
||||
return False, "Failed condition: %s %s %s" % (sourcevalue, condition["condition"]["value"], destinationvalue)
|
||||
return False, {"success": False, "reason": "Failed condition: %s %s %s" % (sourcevalue, condition["condition"]["value"], destinationvalue)}
|
||||
|
||||
|
||||
# Make a general parser here, at least to get param["name"] = param["value"] in maparameter[string]string
|
||||
|
||||
@@ -96,6 +96,8 @@ github.com/frikky/shuffle-shared v0.0.21 h1:xj/XPsXTa2rx41mm4nUc7+2K9RGkq2/mpjSP
|
||||
github.com/frikky/shuffle-shared v0.0.21/go.mod h1:H7SqOta/EAYnfYuWzwzYSh/oWfF0kgnuaJTQNKQBvoQ=
|
||||
github.com/frikky/shuffle-shared v0.0.22 h1:TFMcJCNmOOSneMMWbg5dNzp2z6m0aZLROuL+bzVToRE=
|
||||
github.com/frikky/shuffle-shared v0.0.22/go.mod h1:H7SqOta/EAYnfYuWzwzYSh/oWfF0kgnuaJTQNKQBvoQ=
|
||||
github.com/frikky/shuffle-shared v0.0.23 h1:Pnlc2M6fHnFRLFd5K1iLTVv4/t4P04Ri1GJ5CMxzq0U=
|
||||
github.com/frikky/shuffle-shared v0.0.23/go.mod h1:H7SqOta/EAYnfYuWzwzYSh/oWfF0kgnuaJTQNKQBvoQ=
|
||||
github.com/getkin/kin-openapi v0.8.0 h1:a6TQjTqwkyscC4/hShJX7WhCVE+4bi9lzw61XHQW5hE=
|
||||
github.com/getkin/kin-openapi v0.8.0/go.mod h1:zZQMFkVgRHCdhgb6ihCTIo9dyDZFvX0k/xAKqw1FhPw=
|
||||
github.com/getkin/kin-openapi v0.52.0 h1:6WqsF5d6PfJ8AscdD+9Rtb2RP2iBWyC7V6GcjssWg7M=
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@ version: '3'
|
||||
services:
|
||||
frontend:
|
||||
#build: ./frontend
|
||||
image: ghcr.io/frikky/shuffle-frontend:0.8.64
|
||||
image: ghcr.io/frikky/shuffle-frontend:0.8.71
|
||||
container_name: shuffle-frontend
|
||||
hostname: shuffle-frontend
|
||||
ports:
|
||||
@@ -17,7 +17,7 @@ services:
|
||||
- backend
|
||||
backend:
|
||||
#build: ./backend
|
||||
image: ghcr.io/frikky/shuffle-backend:0.8.64
|
||||
image: ghcr.io/frikky/shuffle-backend:0.8.71
|
||||
container_name: shuffle-backend
|
||||
hostname: ${BACKEND_HOSTNAME}
|
||||
# Here for debugging:
|
||||
@@ -47,7 +47,7 @@ services:
|
||||
- database
|
||||
orborus:
|
||||
#build: ./functions/onprem/orborus
|
||||
image: ghcr.io/frikky/shuffle-orborus:0.8.64
|
||||
image: ghcr.io/frikky/shuffle-orborus:0.8.71
|
||||
container_name: shuffle-orborus
|
||||
hostname: shuffle-orborus
|
||||
networks:
|
||||
@@ -56,7 +56,7 @@ services:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- SHUFFLE_APP_SDK_VERSION=0.8.60
|
||||
- SHUFFLE_WORKER_VERSION=0.8.70
|
||||
- SHUFFLE_WORKER_VERSION=0.8.71
|
||||
- ORG_ID=${ORG_ID}
|
||||
- ENVIRONMENT_NAME=${ENVIRONMENT_NAME}
|
||||
- BASE_URL=http://${OUTER_HOSTNAME}:${BACKEND_PORT}
|
||||
|
||||
+1
-26
@@ -13,6 +13,7 @@ import EditWebhook from "./views/EditWebhook";
|
||||
import AngularWorkflow from "./views/AngularWorkflow";
|
||||
|
||||
import Header from './components/Header';
|
||||
import theme from './theme'
|
||||
import Apps from './views/Apps';
|
||||
import AppCreator from './views/AppCreator';
|
||||
|
||||
@@ -44,34 +45,8 @@ if (window.location.protocol == "http:" && window.location.port === "3000") {
|
||||
//globalUrl = "http://localhost:5002"
|
||||
}
|
||||
|
||||
const theme = createMuiTheme({
|
||||
palette: {
|
||||
primary: {
|
||||
main: "#f85a3e"
|
||||
},
|
||||
secondary: {
|
||||
main: '#e8eaf6',
|
||||
},
|
||||
surfaceColor: "#27292d",
|
||||
inputColor: "#383B40"
|
||||
},
|
||||
typography: {
|
||||
useNextVariants: true
|
||||
},
|
||||
overrides: {
|
||||
MuiMenu: {
|
||||
list: {
|
||||
backgroundColor: "#383B40",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// FIXME - set client side cookies
|
||||
const App = (message, props) => {
|
||||
const [userdata, setUserData] = useState({});
|
||||
//const [homePage, ] = useState(true);
|
||||
const [cookies, setCookie, removeCookie] = useCookies([]);
|
||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
||||
const [dataset, setDataset] = useState(false);
|
||||
|
||||
@@ -47,7 +47,6 @@ const data = [{
|
||||
css: {
|
||||
'width': '30px',
|
||||
'height': '30px',
|
||||
'font-size': '0px',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -118,6 +117,8 @@ const data = [{
|
||||
css: {
|
||||
'shape': 'ellipse',
|
||||
'border-color': '#80deea',
|
||||
'width': '80px',
|
||||
'height': '80px',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2777,11 +2777,12 @@ const AngularWorkflow = (props) => {
|
||||
const [hover, setHover] = React.useState(false)
|
||||
|
||||
const maxlen = 24
|
||||
var newAppname = app.name.replace("_", " ", -1)
|
||||
var newAppname = app.name
|
||||
newAppname = newAppname.charAt(0).toUpperCase()+newAppname.substring(1)
|
||||
if (newAppname.length > maxlen) {
|
||||
newAppname = newAppname.slice(0, maxlen)+".."
|
||||
}
|
||||
app.name.replaceAll("_", " ", -1)
|
||||
|
||||
//const image = "url("+app.large_image+")"
|
||||
const image = app.large_image
|
||||
@@ -2807,13 +2808,17 @@ const AngularWorkflow = (props) => {
|
||||
</Grid>
|
||||
<Grid style={{display: "flex", flexDirection: "column", marginLeft: "20px", minWidth: 185, maxWidth: 185, overflow: "hidden", maxHeight: 77, }}>
|
||||
<Grid item style={{flex: 1}}>
|
||||
<h4 style={{marginBottom: 0, marginTop: 5}}>{newAppname}</h4>
|
||||
<Typography variant="body1" style={{marginBottom: 0, marginTop: 5}}>{newAppname}</Typography>
|
||||
</Grid>
|
||||
<Grid item style={{flex: 1}}>
|
||||
Version: {app.app_version}
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
Version: {app.app_version}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item style={{flex: 1, width: "100%", maxHeight: 27, overflow: "hidden",}}>
|
||||
{app.description}
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
{app.description}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -2833,43 +2838,52 @@ const AngularWorkflow = (props) => {
|
||||
return(
|
||||
<div style={appViewStyle}>
|
||||
<div style={{flex: "1"}}>
|
||||
<TextField
|
||||
style={{backgroundColor: inputColor, borderRadius: borderRadius, marginTop: 5, marginRight: 10,}}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
minHeight: 50,
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
fontSize: "1em",
|
||||
},
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<Tooltip title="Run search" placement="top">
|
||||
<SearchIcon style={{cursor: "pointer"}} />
|
||||
</Tooltip>
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"Search Apps"}
|
||||
id="appsearch"
|
||||
onBlur={(event) => {
|
||||
runSearch(event)
|
||||
}}
|
||||
/>
|
||||
<div style={appScrollStyle}>
|
||||
{visibleApps.map((app, index) => {
|
||||
if (app.invalid) {
|
||||
return null
|
||||
}
|
||||
|
||||
return(
|
||||
<ParsedAppPaper key={index} app={app} />
|
||||
<TextField
|
||||
style={{backgroundColor: inputColor, borderRadius: borderRadius, marginTop: 5, marginRight: 10,}}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
minHeight: 50,
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
fontSize: "1em",
|
||||
},
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<Tooltip title="Run search" placement="top">
|
||||
<SearchIcon style={{cursor: "pointer"}} />
|
||||
</Tooltip>
|
||||
</InputAdornment>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
placeholder={"Search Active Apps"}
|
||||
id="appsearch"
|
||||
onBlur={(event) => {
|
||||
runSearch(event)
|
||||
}}
|
||||
/>
|
||||
{visibleApps.length > 0 ?
|
||||
<div style={appScrollStyle}>
|
||||
{visibleApps.map((app, index) => {
|
||||
if (app.invalid) {
|
||||
return null
|
||||
}
|
||||
|
||||
return(
|
||||
<ParsedAppPaper key={index} app={app} />
|
||||
)
|
||||
})}
|
||||
</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>
|
||||
)
|
||||
@@ -2925,13 +2939,13 @@ const AngularWorkflow = (props) => {
|
||||
//
|
||||
const selectedNameChange = (event) => {
|
||||
//console.log("OLDNAME: ", selectedAction.name)
|
||||
event.target.value = event.target.value.replace("(", "")
|
||||
event.target.value = event.target.value.replace(")", "")
|
||||
event.target.value = event.target.value.replace("$", "")
|
||||
event.target.value = event.target.value.replace("#", "")
|
||||
event.target.value = event.target.value.replace(".", "")
|
||||
event.target.value = event.target.value.replace(",", "")
|
||||
event.target.value = event.target.value.replace(" ", "_")
|
||||
event.target.value = event.target.value.replaceAll("(", "")
|
||||
event.target.value = event.target.value.replaceAll(")", "")
|
||||
event.target.value = event.target.value.replaceAll("$", "")
|
||||
event.target.value = event.target.value.replaceAll("#", "")
|
||||
event.target.value = event.target.value.replaceAll(".", "")
|
||||
event.target.value = event.target.value.replaceAll(",", "")
|
||||
event.target.value = event.target.value.replaceAll(" ", "_")
|
||||
selectedAction.label = event.target.value
|
||||
setSelectedAction(selectedAction)
|
||||
|
||||
@@ -4384,10 +4398,10 @@ const AngularWorkflow = (props) => {
|
||||
newActionname = data.label
|
||||
}
|
||||
// ROFL FIXME - loop
|
||||
newActionname = newActionname.replace("_", " ")
|
||||
newActionname = newActionname.replace("_", " ")
|
||||
newActionname = newActionname.replace("_", " ")
|
||||
newActionname = newActionname.replace("_", " ")
|
||||
newActionname = newActionname.replaceAll("_", " ")
|
||||
newActionname = newActionname.replaceAll("_", " ")
|
||||
newActionname = newActionname.replaceAll("_", " ")
|
||||
newActionname = newActionname.replaceAll("_", " ")
|
||||
newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1)
|
||||
return (
|
||||
<MenuItem key={data.name} style={{maxWidth: 400, overflowX: "hidden", backgroundColor: inputColor, color: "white"}} value={data.name}>
|
||||
@@ -6877,7 +6891,7 @@ const AngularWorkflow = (props) => {
|
||||
// console.log("HANDLE INPUT FIELD FOR COPY!")
|
||||
//}
|
||||
|
||||
to_be_copied.replace(" ", "_")
|
||||
to_be_copied.replaceAll(" ", "_")
|
||||
const elementName = "copy_element_shuffle"
|
||||
var copyText = document.getElementById(elementName);
|
||||
if (copyText !== null && copyText !== undefined) {
|
||||
@@ -7023,37 +7037,59 @@ const AngularWorkflow = (props) => {
|
||||
</Tooltip>
|
||||
</div>
|
||||
{executionData.status !== undefined && executionData.status.length > 0 ?
|
||||
<div>
|
||||
<b>Status: </b>{executionData.status}
|
||||
<div style={{display: "flex"}}>
|
||||
<Typography variant="body1">
|
||||
<b>Status </b>
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
{executionData.status}
|
||||
</Typography>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
{executionData.execution_source !== undefined && executionData.execution_source !== null && executionData.execution_source.length > 0 && executionData.execution_source !== "default" ?
|
||||
<div>
|
||||
<b>Source: </b>{executionData.execution_parent !== null && executionData.execution_parent !== undefined && executionData.execution_parent.length > 0 ?
|
||||
executionData.execution_source === props.match.params.key ?
|
||||
<span style={{cursor: "pointer", color: "#f85a3e"}} onClick={(event) => {
|
||||
getWorkflowExecution(props.match.params.key, executionData.execution_parent)
|
||||
}}>
|
||||
Parent Execution
|
||||
</span>
|
||||
<div style={{display: "flex"}}>
|
||||
<Typography variant="body1">
|
||||
<b>Source </b>
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
{executionData.execution_parent !== null && executionData.execution_parent !== undefined && executionData.execution_parent.length > 0 ?
|
||||
executionData.execution_source === props.match.params.key ?
|
||||
|
||||
<span style={{cursor: "pointer", color: "#f85a3e"}} onClick={(event) => {
|
||||
getWorkflowExecution(props.match.params.key, executionData.execution_parent)
|
||||
}}>
|
||||
Parent Execution
|
||||
</span>
|
||||
|
||||
:
|
||||
<a rel="norefferer" href={`/workflows/${executionData.execution_source}?view=executions&execution_id=${executionData.execution_parent}`} target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>Parent Workflow</a>
|
||||
:
|
||||
<a rel="norefferer" href={`/workflows/${executionData.execution_source}?view=executions&execution_id=${executionData.execution_parent}`} target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>Parent Workflow</a>
|
||||
:
|
||||
executionData.execution_source
|
||||
}
|
||||
executionData.execution_source
|
||||
}
|
||||
</Typography>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
{executionData.started_at !== undefined ?
|
||||
<div>
|
||||
<b>Started: </b>{new Date(executionData.started_at*1000).toISOString()}
|
||||
<div style={{display: "flex"}}>
|
||||
<Typography variant="body1">
|
||||
<b>Started </b>
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
{new Date(executionData.started_at*1000).toISOString()}
|
||||
</Typography>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
{executionData.completed_at !== undefined && executionData.completed_at !== null && executionData.completed_at > 0 ?
|
||||
<div>
|
||||
<b>Finished: </b>{new Date(executionData.completed_at*1000).toISOString()}
|
||||
<div style={{display: "flex"}}>
|
||||
<Typography variant="body1">
|
||||
<b>Finished </b>
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
{new Date(executionData.completed_at*1000).toISOString()}
|
||||
</Typography>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
@@ -7153,10 +7189,21 @@ const AngularWorkflow = (props) => {
|
||||
{actionimg}
|
||||
<div>
|
||||
<div style={{fontSize: 24, marginTop: "auto", marginBottom: "auto"}}><b>{data.action.label}</b></div>
|
||||
<div style={{fontSize: 14}}>{data.action.name}</div>
|
||||
<div style={{fontSize: 14}}>
|
||||
<Typography variant="body2" color="textsecondary">
|
||||
{data.action.name}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{marginBottom: 5}}><b>Status </b> {data.status}</div>
|
||||
<div style={{marginBottom: 5, display: "flex",}}>
|
||||
<Typography variant="body1">
|
||||
<b>Status </b>
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
{data.status}
|
||||
</Typography>
|
||||
</div>
|
||||
{validate.valid ? <span><ReactJson
|
||||
src={validate.result}
|
||||
theme="solarized"
|
||||
@@ -7188,9 +7235,13 @@ const AngularWorkflow = (props) => {
|
||||
}
|
||||
</span>
|
||||
:
|
||||
<div style={{maxHeight: 250, overflowX: "hidden", overflowY: "auto", whiteSpace: "pre-wrap"}}>
|
||||
<b>Result</b>
|
||||
{data.result}
|
||||
<div style={{maxHeight: 250, overflowX: "hidden", overflowY: "auto", whiteSpace: "pre-wrap", }}>
|
||||
<Typography variant="body1" style={{display: 'inline-block'}}>
|
||||
<b>Result</b>
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary" style={{display: 'inline-block'}}>
|
||||
{data.result}
|
||||
</Typography>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
+51
-39
@@ -16,6 +16,10 @@ import Dropzone from '../components/Dropzone';
|
||||
const surfaceColor = "#27292D"
|
||||
const inputColor = "#383B40"
|
||||
|
||||
const chipStyle = {
|
||||
backgroundColor: "#3d3f43", height: 30, marginRight: 5, paddingLeft: 5, paddingRight: 5, height: 28, cursor: "pointer", borderColor: "#3d3f43", color: "white",
|
||||
}
|
||||
|
||||
// Parses JSON data into keys that can be used everywhere :)
|
||||
export const GetParsedPaths = (inputdata, basekey) => {
|
||||
const splitkey = " > "
|
||||
@@ -173,7 +177,7 @@ const Apps = (props) => {
|
||||
minHeight: 130,
|
||||
maxHeight: 130,
|
||||
minWidth: "100%",
|
||||
maxWidth: "100%",
|
||||
maxWidth: 612.5,
|
||||
marginBottom: 5,
|
||||
borderRadius: 5,
|
||||
color: "white",
|
||||
@@ -341,11 +345,9 @@ const Apps = (props) => {
|
||||
//console.log("IMG LOADED!: ", event.target)
|
||||
}} />
|
||||
|
||||
// FIXME - add label to apps, as this might be slow with A LOT of apps
|
||||
var newAppname = data.name
|
||||
newAppname = newAppname.replace("_", " ")
|
||||
newAppname = newAppname.charAt(0).toUpperCase()+newAppname.substring(1)
|
||||
|
||||
newAppname = newAppname.replaceAll("_", " ")
|
||||
var sharing = "public"
|
||||
if (!data.sharing) {
|
||||
sharing = "private"
|
||||
@@ -361,7 +363,7 @@ const Apps = (props) => {
|
||||
}
|
||||
|
||||
var description = data.description
|
||||
const maxDescLen = 51
|
||||
const maxDescLen = 60
|
||||
if (description.length > maxDescLen) {
|
||||
description = data.description.slice(0, maxDescLen)+"..."
|
||||
}
|
||||
@@ -370,6 +372,7 @@ const Apps = (props) => {
|
||||
return (
|
||||
<Paper square key={data.id} style={paperAppStyle} onClick={() => {
|
||||
if (selectedApp.id !== data.id) {
|
||||
data.name = newAppname
|
||||
setSelectedApp(data)
|
||||
|
||||
console.log(data)
|
||||
@@ -389,17 +392,21 @@ const Apps = (props) => {
|
||||
{imageline}
|
||||
</ButtonBase>
|
||||
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: boxWidth, backgroundColor: boxColor}}/>
|
||||
<Grid container style={{margin: "0px 10px 10px 10px", flex: "1"}}>
|
||||
<Grid style={{display: "flex", flexDirection: "column", width: "100%"}}>
|
||||
<Grid container style={{margin: "0px 0px 10px 10px", flex: "1"}}>
|
||||
<Grid style={{display: "flex", flexDirection: "column", }}>
|
||||
<Grid item style={{flex: "1"}}>
|
||||
<h3 style={{marginBottom: "0px"}}>{newAppname}</h3>
|
||||
<Typography variant="body1" style={{marginBottom: "0px", marginTop: 5,}}>
|
||||
{newAppname}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<div style={{display: "flex", flex: "1"}}>
|
||||
<Grid item style={{flex: "1", justifyContent: "center", overflow: "hidden"}}>
|
||||
{description}
|
||||
<div style={{display: "flex", flex: "1", marginTop: 5,}}>
|
||||
<Grid item style={{flex: 1, justifyContent: "center", overflow: "hidden", maxHeight: 43, overflow: "hidden",}}>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
{description}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</div>
|
||||
<Grid item style={{flex: "1", justifyContent: "center", marginTop: 5}}>
|
||||
<Grid item style={{flex: 1, justifyContent: "center", marginTop: 8}}>
|
||||
{data.tags === null || data.tags === undefined ? null : data.tags.map((tag, index) => {
|
||||
if (index >= 3) {
|
||||
return null
|
||||
@@ -408,7 +415,7 @@ const Apps = (props) => {
|
||||
return (
|
||||
<Chip
|
||||
key={index}
|
||||
style={{height: 25, marginRight: 5, cursor: "pointer",}}
|
||||
style={chipStyle}
|
||||
label={tag}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
@@ -450,7 +457,7 @@ const Apps = (props) => {
|
||||
// FIXME - add label to apps, as this might be slow with A LOT of apps
|
||||
var newAppname = selectedApp.name
|
||||
if (newAppname !== undefined && newAppname.length > 0) {
|
||||
newAppname = newAppname.replace("_", " ")
|
||||
newAppname = newAppname.replaceAll("_", " ")
|
||||
newAppname = newAppname.charAt(0).toUpperCase()+newAppname.substring(1)
|
||||
} else {
|
||||
newAppname = ""
|
||||
@@ -613,9 +620,15 @@ const Apps = (props) => {
|
||||
{imageline}
|
||||
</div>
|
||||
<div style={{maxWidth: "85%", overflow: "hidden"}}>
|
||||
<h2 style={{marginTop: 20, marginBottom: 0, }}>{newAppname}</h2>
|
||||
<p style={{marginTop: 5, marginBottom: 0,}}>Version {selectedApp.app_version}</p>
|
||||
<p style={{marginTop: 5, marginBottom: 0, maxHeight: 150, overflowY: "auto", overflowX: "hidden",}}>{description}</p>
|
||||
<Typography variant="h6" style={{marginBottom: 0, }}>
|
||||
{newAppname}
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
Version {selectedApp.app_version}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="textSecondary" style={{marginTop: 5, marginBottom: 0, maxHeight: 150, overflowY: "auto", overflowX: "hidden",}}>
|
||||
{description}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
{isCloud ?
|
||||
@@ -644,7 +657,7 @@ const Apps = (props) => {
|
||||
return (
|
||||
<Chip
|
||||
key={index}
|
||||
style={{height: 25, marginRight: 5, marginTop: 7, cursor: "pointer",}}
|
||||
style={chipStyle}
|
||||
variant="outlined"
|
||||
label={tag}
|
||||
color="primary"
|
||||
@@ -656,7 +669,7 @@ const Apps = (props) => {
|
||||
{props.userdata !== undefined && props.userdata.id === selectedApp.owner ?
|
||||
<div style={{marginTop: 15}}>
|
||||
{/*<p><b>ID:</b> {selectedApp.id}</p>*/}
|
||||
<b style={{marginRight: 15}}>Sharing:</b>
|
||||
<b style={{marginRight: 15}}>Sharing </b>
|
||||
<Select
|
||||
value={sharingConfiguration}
|
||||
onChange={(event) => {
|
||||
@@ -713,12 +726,7 @@ const Apps = (props) => {
|
||||
>
|
||||
{selectedApp.actions.map(data => {
|
||||
var newActionname = data.label !== undefined && data.label.length > 0 ? data.label : data.name
|
||||
|
||||
// ROFL FIXME - loop
|
||||
newActionname = newActionname.replace("_", " ")
|
||||
newActionname = newActionname.replace("_", " ")
|
||||
newActionname = newActionname.replace("_", " ")
|
||||
newActionname = newActionname.replace("_", " ")
|
||||
newActionname = newActionname.replaceAll("_", " ")
|
||||
newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1)
|
||||
return (
|
||||
<MenuItem key={data.name} style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
||||
@@ -777,7 +785,9 @@ const Apps = (props) => {
|
||||
- <a href="https://apis.guru/browse-apis/" style={{textDecoration: "none", color: "#f85a3e"}} target="_blank">OpenAPI directory</a>
|
||||
- <a href="https://editor.swagger.io/" style={{textDecoration: "none", color: "#f85a3e"}} target="_blank">OpenAPI Validator</a>
|
||||
<div/>
|
||||
Apps interact with eachother in workflows. They are created with the app creator, using OpenAPI specification or manually in python. The links above are references to OpenAPI tools and other app repositories. There's thousands of them.
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
Apps interact with eachother in workflows. They are created with the app creator, using OpenAPI specification or manually in python. The links above are references to OpenAPI tools and other app repositories. There's thousands of them.
|
||||
</Typography>
|
||||
<div/>
|
||||
<Divider style={{height: 1, backgroundColor: dividerColor, marginTop: 20, marginBottom: 20}} />
|
||||
<div style={{}}>
|
||||
@@ -795,7 +805,7 @@ const Apps = (props) => {
|
||||
OR
|
||||
<Link to="/apps/new" style={{marginLeft: 5, textDecoration: "none", color: "#f85a3e"}}>
|
||||
<Button
|
||||
variant="text"
|
||||
variant="outlined"
|
||||
component="label"
|
||||
color="primary"
|
||||
style={{}}
|
||||
@@ -872,29 +882,31 @@ const Apps = (props) => {
|
||||
const appView = isLoggedIn ?
|
||||
<Dropzone style={{maxWidth: window.innerWidth > 1366 ? 1366 : 1200, margin: "auto", padding: 20 }} onDrop={uploadFile}>
|
||||
<div style={appViewStyle}>
|
||||
<div style={{flex: 1}}>
|
||||
<div style={{flex: 1, }}>
|
||||
<Breadcrumbs aria-label="breadcrumb" separator="›" style={{color: "white",}}>
|
||||
<Link to="/apps" style={{textDecoration: "none", color: "inherit",}}>
|
||||
<h2 style={{color: "rgba(255,255,255,0.5)"}}>
|
||||
<Typography variant="h6" style={{color: "rgba(255,255,255,0.5)"}}>
|
||||
<AppsIcon style={{marginRight: 10}} />
|
||||
App upload
|
||||
</h2>
|
||||
</Typography>
|
||||
</Link>
|
||||
{selectedApp.activated && selectedApp.private_id !== undefined && selectedApp.private_id.length > 0 && selectedApp.generated ?
|
||||
<Link to={`/apps/edit/${selectedApp.id}`} style={{textDecoration: "none", color: "inherit",}}>
|
||||
<h2>
|
||||
<Typography variant="h6">
|
||||
{selectedApp.name}
|
||||
</h2>
|
||||
</Typography>
|
||||
</Link>
|
||||
: null}
|
||||
</Breadcrumbs>
|
||||
<div style={{marginTop: 15}} />
|
||||
<UploadView/>
|
||||
</div>
|
||||
<Divider style={{marginBottom: 10, marginTop: 10, height: "100%", width: 1, backgroundColor: dividerColor}}/>
|
||||
<div style={{flex: 1, marginLeft: 10, marginRight: 10}}>
|
||||
<div style={{display: "flex", minHeight: 84.81}}>
|
||||
<div style={{flex: 1}}>
|
||||
<h2>Activated apps ({apps.length+searchableApps.length})</h2>
|
||||
<div style={{flex: 1, marginLeft: 10, marginRight: 10, }}>
|
||||
<div style={{display: "flex",}}>
|
||||
<div style={{flex: 1, marginBottom: 15, }}>
|
||||
<Typography variant="h6">
|
||||
Activated apps ({apps.length+searchableApps.length})
|
||||
</Typography>
|
||||
</div>
|
||||
{isCloud ? null :
|
||||
<span>
|
||||
@@ -969,9 +981,9 @@ const Apps = (props) => {
|
||||
<Paper square style={uploadViewPaperStyle}>
|
||||
<Typography style={{margin: 10, }}>
|
||||
<span>
|
||||
<Link to={"https://shuffler.io/search"} style={{textDecoration: "none", color: "#f85a3e"}}>
|
||||
<a href={"https://shuffler.io/search"} style={{textDecoration: "none", color: "#f85a3e"}} target="_blank">
|
||||
Click here
|
||||
</Link> to search ALL apps, not just your activated ones.
|
||||
</a> to search ALL apps, not just your activated ones.
|
||||
</span>
|
||||
</Typography>
|
||||
<div/>
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useEffect} from 'react';
|
||||
import { useInterval } from 'react-powerhooks';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
import {Grid, Paper, Tooltip, Divider, Button, TextField, FormControl, IconButton, Menu, MenuItem, FormControlLabel, Chip, Switch, Typography, Zoom, CircularProgress, Dialog, DialogTitle, DialogActions, DialogContent} from '@material-ui/core';
|
||||
import {Avatar, Grid, Paper, Tooltip, Divider, Button, TextField, FormControl, IconButton, Menu, MenuItem, FormControlLabel, Chip, Switch, Typography, Zoom, CircularProgress, Dialog, DialogTitle, DialogActions, DialogContent} from '@material-ui/core';
|
||||
import {FileCopy as FileCopyIcon, Delete as DeleteIcon, BubbleChart as BubbleChartIcon, Restore as RestoreIcon, Cached as CachedIcon, GetApp as GetAppIcon, Apps as AppsIcon, Edit as EditIcon, MoreVert as MoreVertIcon, PlayArrow as PlayArrowIcon, Add as AddIcon, Publish as PublishIcon, CloudUpload as CloudUploadIcon, CloudDownload as CloudDownloadIcon} from '@material-ui/icons';
|
||||
//import {Search as SearchIcon, ArrowUpward as ArrowUpwardIcon, Visibility as VisibilityIcon, Done as DoneIcon, Close as CloseIcon, Error as ErrorIcon, FindReplace as FindreplaceIcon, ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, Add as AddIcon, Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, Create as CreateIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, MoreVert as MoreVertIcon, Apps as AppsIcon, Schedule as ScheduleIcon, FavoriteBorder as FavoriteBorderIcon, Pause as PauseIcon, Delete as DeleteIcon, AddCircleOutline as AddCircleOutlineIcon, Save as SaveIcon, KeyboardArrowLeft as KeyboardArrowLeftIcon, KeyboardArrowRight as KeyboardArrowRightIcon, ArrowBack as ArrowBackIcon, Settings as SettingsIcon, LockOpen as LockOpenIcon, ExpandMore as ExpandMoreIcon, VpnKey as VpnKeyIcon} from '@material-ui/icons';
|
||||
|
||||
@@ -86,6 +86,10 @@ const fontSize_16 = {fontSize: "16px",}
|
||||
const counterStyle = {fontSize: "36px",fontWeight:"bold"}
|
||||
const blockRightStyle = {textAlign: "right",padding: "20px 20px 0px 0px",width:"100%"}
|
||||
|
||||
const chipStyle = {
|
||||
backgroundColor: "#3d3f43", height: 30, marginRight: 5, paddingLeft: 5, paddingRight: 5, height: 28, cursor: "pointer", borderColor: "#3d3f43", color: "white",
|
||||
}
|
||||
|
||||
const flexContentStyle = {
|
||||
display: "flex",
|
||||
flexDirection: "row"
|
||||
@@ -452,12 +456,10 @@ const Workflows = (props) => {
|
||||
}
|
||||
|
||||
const workflowActionStyle = {
|
||||
flex: "1",
|
||||
display: "flex",
|
||||
width: 150,
|
||||
width: 160,
|
||||
height: 44,
|
||||
justifyContent: "space-between",
|
||||
overflow: "hidden"
|
||||
}
|
||||
|
||||
const executeWorkflow = (id) => {
|
||||
@@ -741,7 +743,7 @@ const Workflows = (props) => {
|
||||
|
||||
var parsedName = data.name
|
||||
if (parsedName !== undefined && parsedName !== null && parsedName.length > 25) {
|
||||
parsedName = parsedName.slice(0,25)+".."
|
||||
parsedName = parsedName.slice(0,26)+".."
|
||||
}
|
||||
|
||||
|
||||
@@ -753,12 +755,14 @@ const Workflows = (props) => {
|
||||
<Paper square style={paperAppStyle} >
|
||||
<div style={{position: "absolute", bottom: 1, left: 1, height: 12, width: 12, backgroundColor: boxColor, borderRadius: "0 100px 0 0",}} />
|
||||
<Grid item style={{display: "flex", flexDirection: "column", width: "100%"}}>
|
||||
<Grid item style={{flex: 1, display: "flex", maxHeight: 34,}}>
|
||||
<Typography variant="h6" style={{marginBottom: 0, paddingBottom: 0, maxHeight: 30, flex: 10,}}>
|
||||
<Link to={"/workflows/"+data.id} style={{textDecoration: "none", color: "inherit",}}>
|
||||
{parsedName}
|
||||
</Link>
|
||||
</Typography>
|
||||
<Grid item style={{display: "flex", maxHeight: 34,}}>
|
||||
<Tooltip title={`Edit ${data.name}`} placement="bottom">
|
||||
<Typography variant="body1" style={{marginBottom: 0, paddingBottom: 0, maxHeight: 30, flex: 10,}}>
|
||||
<Link to={"/workflows/"+data.id} style={{textDecoration: "none", color: "inherit",}}>
|
||||
{parsedName}
|
||||
</Link>
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
<Grid item style={workflowActionStyle}>
|
||||
<Tooltip color="primary" title="Action amount" placement="bottom">
|
||||
@@ -778,7 +782,31 @@ const Workflows = (props) => {
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip color="primary" title="Subflows used" placement="bottom">
|
||||
<span style={{marginLeft: 15, display: "flex", color: "#979797", }}>
|
||||
<span style={{marginLeft: 15, display: "flex", color: "#979797", cursor: "pointer"}} onClick={() => {
|
||||
if (subflows === 0) {
|
||||
alert.info("No subflows for "+data.name)
|
||||
return
|
||||
}
|
||||
|
||||
var newWorkflows = [data]
|
||||
for (var key in data.triggers) {
|
||||
const trigger = data.triggers[key]
|
||||
if (trigger.app_name !== "Shuffle Workflow") {
|
||||
continue
|
||||
}
|
||||
|
||||
if (trigger.parameters !== undefined && trigger.parameters !== null && trigger.parameters.length > 0 && trigger.parameters[0].name === "workflow") {
|
||||
const newWorkflow = workflows.find(item => item.id === trigger.parameters[0].value)
|
||||
if (newWorkflow !== null && newWorkflow !== undefined) {
|
||||
newWorkflows.push(newWorkflow)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setFilters(["Subflows of "+data.name])
|
||||
setFilteredWorkflows(newWorkflows)
|
||||
}}>
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg" style={{color: "#979797", marginTop: "auto", marginBottom: "auto",}}>
|
||||
<path d="M0 0H15V15H0V0ZM16 16H18V18H16V16ZM16 13H18V15H16V13ZM16 10H18V12H16V10ZM16 7H18V9H16V7ZM16 4H18V6H16V4ZM13 16H15V18H13V16ZM10 16H12V18H10V16ZM7 16H9V18H7V16ZM4 16H6V18H4V16Z" fill="#979797"/>
|
||||
</svg>
|
||||
@@ -802,17 +830,18 @@ const Workflows = (props) => {
|
||||
: null}
|
||||
*/}
|
||||
</Grid>
|
||||
<Grid item style={{flex: "1", justifyContent: "left", overflow: "hidden", marginTop: 5,}}>
|
||||
<Grid item style={{justifyContent: "left", overflow: "hidden", marginTop: 5,}}>
|
||||
{data.tags !== undefined ?
|
||||
data.tags.map((tag, index) => {
|
||||
if (index >= 3) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Chip
|
||||
key={index}
|
||||
style={{backgroundColor: "#3d3f43", height: 30, marginRight: 5, paddingLeft: 5, paddingRight: 5, height: 28, cursor: "pointer", borderColor: "#3d3f43", color: "white",}}
|
||||
style={chipStyle}
|
||||
label={tag}
|
||||
onClick={handleChipClick}
|
||||
variant="outlined"
|
||||
@@ -889,6 +918,7 @@ const Workflows = (props) => {
|
||||
|
||||
</Menu>
|
||||
</Grid>
|
||||
{/*
|
||||
<Grid>
|
||||
<Link to={"/workflows/"+data.id}>
|
||||
<Tooltip title="Edit workflow" placement="bottom">
|
||||
@@ -896,6 +926,7 @@ const Workflows = (props) => {
|
||||
</Tooltip>
|
||||
</Link>
|
||||
</Grid>
|
||||
*/}
|
||||
</Grid>
|
||||
: null}
|
||||
</Paper>
|
||||
@@ -1236,7 +1267,7 @@ const Workflows = (props) => {
|
||||
} else if (data.triggers[key].app_name === "Schedule") {
|
||||
schedules += 1
|
||||
//scheduleImg = data.triggers[key].large_image
|
||||
} else if (data.triggers[key].app_name === "Subflow") {
|
||||
} else if (data.triggers[key].app_name === "Shuffle Workflow") {
|
||||
subflows += 1
|
||||
}
|
||||
}
|
||||
@@ -1298,7 +1329,7 @@ const Workflows = (props) => {
|
||||
return (
|
||||
<Chip
|
||||
key={index}
|
||||
style={{backgroundColor: "#3d3f43", height: 30, marginRight: 5, paddingLeft: 5, paddingRight: 5, height: 28, cursor: "pointer", borderColor: "#3d3f43", color: "white",}}
|
||||
style={chipStyle}
|
||||
label={tag}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
@@ -1383,7 +1414,6 @@ const Workflows = (props) => {
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
backgroundColor: inputColor,
|
||||
},
|
||||
}}
|
||||
placeholder="Tags"
|
||||
@@ -1523,27 +1553,6 @@ const Workflows = (props) => {
|
||||
<div style={{flex: 3}}>
|
||||
<h2>Workflows</h2>
|
||||
</div>
|
||||
<div style={{flex: 2, float: "right", marginTop: 10,}}>
|
||||
<ChipInput
|
||||
style={{}}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
placeholder="Filters"
|
||||
color="primary"
|
||||
fullWidth
|
||||
value={filters}
|
||||
onAdd={(chip) => {
|
||||
addFilter(chip)
|
||||
}}
|
||||
onDelete={(chip, index) => {
|
||||
removeFilter(index)
|
||||
//setUpdate("delete "+chip)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/*
|
||||
@@ -1578,11 +1587,49 @@ const Workflows = (props) => {
|
||||
</div>
|
||||
*/}
|
||||
|
||||
<div style={{display: "flex", margin: "20px 0px 20px 0px"}}>
|
||||
<div style={{flex: 10}}>
|
||||
<Typography>Your workflow view. <a rel="norefferer" target="_blank" href="https://shuffler.io/docs/workflows" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>Learn more about Workflows</a></Typography>
|
||||
{/*
|
||||
chipRenderer={({ value, isFocused, isDisabled, handleClick, handleRequestDelete }, key) => {
|
||||
console.log("VALUE: ", value)
|
||||
|
||||
return (
|
||||
<Chip
|
||||
key={key}
|
||||
style={chipStyle}
|
||||
|
||||
>
|
||||
{value}
|
||||
</Chip>
|
||||
)
|
||||
}}
|
||||
*/}
|
||||
<div style={{display: "flex", margin: "0px 0px 20px 0px"}}>
|
||||
<div style={{flex: 1}}>
|
||||
<Typography style={{marginTop: 7, marginBottom: "auto"}}>
|
||||
<a rel="norefferer" target="_blank" href="https://shuffler.io/docs/workflows" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>Learn more about Workflows</a>
|
||||
</Typography>
|
||||
</div>
|
||||
<div style={{float: "right",}}>
|
||||
<div style={{flex: 1, float: "right",}}>
|
||||
<ChipInput
|
||||
style={{}}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
//backgroundColor: inputColor,
|
||||
},
|
||||
}}
|
||||
placeholder="Filter Your Workflows"
|
||||
color="primary"
|
||||
fullWidth
|
||||
value={filters}
|
||||
onAdd={(chip) => {
|
||||
addFilter(chip)
|
||||
}}
|
||||
onDelete={(chip, index) => {
|
||||
removeFilter(index)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{float: "right", flex: 1, textAlign: "right",}}>
|
||||
{workflowButtons}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
NAME=shuffle-orborus
|
||||
VERSION=0.8.70
|
||||
VERSION=0.8.71
|
||||
|
||||
echo "Running docker build with $NAME:$VERSION"
|
||||
#docker rmi frikky/shuffle:$NAME --force
|
||||
|
||||
@@ -9,7 +9,7 @@ require (
|
||||
github.com/docker/docker v20.10.1+incompatible
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/frikky/shuffle-shared v0.0.12 // indirect
|
||||
github.com/frikky/shuffle-shared v0.0.23 // indirect
|
||||
github.com/gogo/protobuf v1.3.1 // indirect
|
||||
github.com/mackerelio/go-osstat v0.1.0
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
|
||||
@@ -537,8 +537,8 @@ func main() {
|
||||
|
||||
// Doesn't work because of USER INPUT
|
||||
if found {
|
||||
//log.Printf("[INFO] Skipping duplicate %s", execution.ExecutionId)
|
||||
//continue
|
||||
log.Printf("[INFO] Skipping duplicate %s", execution.ExecutionId)
|
||||
continue
|
||||
} else {
|
||||
//log.Printf("[INFO] Adding to be ran %s", execution.ExecutionId)
|
||||
executionIds = append(executionIds, execution.ExecutionId)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
NAME=shuffle-worker
|
||||
VERSION=0.8.70
|
||||
VERSION=0.8.71
|
||||
|
||||
echo "Running docker build with $NAME:$VERSION"
|
||||
#CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o worker.bin .
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
module worker
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/containerd/containerd v1.4.4 // indirect
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/docker v20.10.5+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/frikky/shuffle-shared v0.0.20 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
)
|
||||
Reference in New Issue
Block a user