Multiple frontend & backend fixes
This commit is contained in:
@@ -454,12 +454,9 @@ const Header = (props) => {
|
|||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then(function (responseJson) {
|
.then(function (responseJson) {
|
||||||
|
console.log("In here?")
|
||||||
if (responseJson.success === true) {
|
if (responseJson.success === true) {
|
||||||
if (
|
if (responseJson.region_url !== undefined && responseJson.region_url !== null && responseJson.region_url.length > 0) {
|
||||||
responseJson.region_url !== undefined &&
|
|
||||||
responseJson.region_url !== null &&
|
|
||||||
responseJson.region_url.length > 0
|
|
||||||
) {
|
|
||||||
console.log("Region Change: ", responseJson.region_url);
|
console.log("Region Change: ", responseJson.region_url);
|
||||||
localStorage.setItem("globalUrl", responseJson.region_url);
|
localStorage.setItem("globalUrl", responseJson.region_url);
|
||||||
//globalUrl = responseJson.region_url
|
//globalUrl = responseJson.region_url
|
||||||
@@ -468,9 +465,14 @@ const Header = (props) => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
toast("Successfully changed active organization - refreshing!");
|
toast("Successfully changed active organization - refreshing!");
|
||||||
} else {
|
} else {
|
||||||
toast("Failed changing org: ", responseJson.reason);
|
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.length > 0) {
|
||||||
|
toast(responseJson.reason);
|
||||||
|
} else {
|
||||||
|
toast("Failed changing org. Try again or contact support@shuffler.io if this persists.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { NestedMenuItem } from "mui-nested-menu";
|
|||||||
//import { useAlert
|
//import { useAlert
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
Chip,
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
Popper,
|
Popper,
|
||||||
TextField,
|
TextField,
|
||||||
@@ -3298,14 +3299,12 @@ const ParsedAction = (props) => {
|
|||||||
<Typography style={{color: "rgba(255,255,255,0.7)"}}>Authentication</Typography>
|
<Typography style={{color: "rgba(255,255,255,0.7)"}}>Authentication</Typography>
|
||||||
<div style={{ display: "flex" }}>
|
<div style={{ display: "flex" }}>
|
||||||
<Select
|
<Select
|
||||||
MenuProps={{
|
MenuProps={{
|
||||||
disableScrollLock: true,
|
disableScrollLock: true,
|
||||||
}}
|
}}
|
||||||
labelId="select-app-auth"
|
labelId="select-app-auth"
|
||||||
value={
|
value={
|
||||||
Object.getOwnPropertyNames(
|
Object.getOwnPropertyNames(selectedAction.selectedAuthentication).length === 0
|
||||||
selectedAction.selectedAuthentication
|
|
||||||
).length === 0
|
|
||||||
? "No selection"
|
? "No selection"
|
||||||
: selectedAction.selectedAuthentication
|
: selectedAction.selectedAuthentication
|
||||||
}
|
}
|
||||||
@@ -3353,7 +3352,11 @@ const ParsedAction = (props) => {
|
|||||||
<em>No selection</em>
|
<em>No selection</em>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{selectedAction.authentication.map((data) => {
|
{selectedAction.authentication.map((data) => {
|
||||||
//console.log("AUTH DATA: ", data)
|
console.log("AUTH DATA: ", data)
|
||||||
|
if (data.last_modified === true) {
|
||||||
|
console.log("LAST MODIFIED: ", data.label)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={data.id}
|
key={data.id}
|
||||||
@@ -3363,7 +3366,21 @@ const ParsedAction = (props) => {
|
|||||||
}}
|
}}
|
||||||
value={data}
|
value={data}
|
||||||
>
|
>
|
||||||
{data.label} - ({data.app.app_version})
|
{data.last_modified === true ?
|
||||||
|
<Chip
|
||||||
|
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer",}}
|
||||||
|
label={"Latest"}
|
||||||
|
variant="outlined"
|
||||||
|
color="secondary"
|
||||||
|
/>
|
||||||
|
: null}
|
||||||
|
<Chip
|
||||||
|
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer",}}
|
||||||
|
label={data.app.app_version}
|
||||||
|
variant="outlined"
|
||||||
|
color="secondary"
|
||||||
|
/>
|
||||||
|
{data.label}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -3449,6 +3466,14 @@ const ParsedAction = (props) => {
|
|||||||
}}
|
}}
|
||||||
value={data.Name}
|
value={data.Name}
|
||||||
>
|
>
|
||||||
|
{data.default === true ?
|
||||||
|
<Chip
|
||||||
|
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer",}}
|
||||||
|
label={"Default"}
|
||||||
|
variant="outlined"
|
||||||
|
color="secondary"
|
||||||
|
/>
|
||||||
|
: null}
|
||||||
{data.Name}
|
{data.Name}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
@@ -3562,7 +3587,7 @@ const ParsedAction = (props) => {
|
|||||||
options={selectedApp.actions === undefined || selectedApp.actions === null ? [] : selectedApp.actions.filter((a) => a.category_label !== undefined && a.category_label !== null && a.category_label.length > 0).concat(sortByKey(selectedApp.actions, "label"))}
|
options={selectedApp.actions === undefined || selectedApp.actions === null ? [] : selectedApp.actions.filter((a) => a.category_label !== undefined && a.category_label !== null && a.category_label.length > 0).concat(sortByKey(selectedApp.actions, "label"))}
|
||||||
ListboxProps={{
|
ListboxProps={{
|
||||||
style: {
|
style: {
|
||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: theme.palette.surfaceColor,
|
||||||
color: "white",
|
color: "white",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -42,14 +42,20 @@ const chipStyle = {
|
|||||||
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240")
|
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240")
|
||||||
const SearchData = props => {
|
const SearchData = props => {
|
||||||
const { serverside, userdata, setModalOpen, modalOpen } = props
|
const { serverside, userdata, setModalOpen, modalOpen } = props
|
||||||
|
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
const borderRadius = 3
|
const borderRadius = 3
|
||||||
const node = useRef()
|
const node = useRef()
|
||||||
const [searchOpen, setSearchOpen] = useState(true)
|
const [searchOpen, setSearchOpen] = useState(false)
|
||||||
|
const [oldPath, setOldPath] = useState("")
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
const [userTyped, setUserTyped] = useState(false)
|
|
||||||
|
|
||||||
|
const handleLinkClick = () => {
|
||||||
|
if (modalOpen) {
|
||||||
|
setModalOpen(false); // Assuming setModalOpen is defined correctly
|
||||||
|
} else {
|
||||||
|
console.log("Condition not met, staying on the same page");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (serverside === true) {
|
if (serverside === true) {
|
||||||
return null
|
return null
|
||||||
@@ -72,37 +78,36 @@ const SearchData = props => {
|
|||||||
// }, searchOpen)
|
// }, searchOpen)
|
||||||
|
|
||||||
const SearchBox = ({ currentRefinement, refine, isSearchStalled, }) => {
|
const SearchBox = ({ currentRefinement, refine, isSearchStalled, }) => {
|
||||||
|
const [inputValue, setInputValue] = useState(currentRefinement);
|
||||||
|
|
||||||
|
const textFieldRef = useRef(null);
|
||||||
const keyPressHandler = (e) => {
|
const keyPressHandler = (e) => {
|
||||||
// e.preventDefault();
|
|
||||||
if (e.which === 13) {
|
if (e.which === 13) {
|
||||||
// alert("You pressed enter!");
|
// navigate(`/search?q=${currentRefinement}`, { state: value, replace: true });
|
||||||
navigate("/search?q=" + currentRefinement, { state: value, replace: true });
|
// setModalOpen(false);
|
||||||
|
const trimmedValue = inputValue.trim();
|
||||||
setSearchOpen(false)
|
if (trimmedValue !== '') {
|
||||||
setModalOpen(false)
|
e.preventDefault();
|
||||||
return
|
navigate(`/search?q=${trimmedValue}`, { state: trimmedValue, replace: true });
|
||||||
|
setModalOpen(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
endAdornment: (
|
useEffect(() => {
|
||||||
<InputAdornment position="end" style={{textAlign: "right", zIndex: 5001, cursor: "pointer", width: 100, }} onMouseOver={(event) => {
|
if (searchOpen && textFieldRef.current) {
|
||||||
event.preventDefault()
|
textFieldRef.current.focus();
|
||||||
}}>
|
}
|
||||||
<CloseIcon style={{marginRight: 5,}} onClick={() => {
|
}, [searchOpen]);
|
||||||
setSearchOpen(false)
|
|
||||||
}} />
|
|
||||||
</InputAdornment>
|
|
||||||
),
|
|
||||||
*/
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<form id="search_form" noValidate type="searchbox" action="" role="search" onClick={() => {
|
<form id="search_form" noValidate type="searchbox" action="" role="search" onClick={() => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
style={{ zIndex: 1100, marginTop:-20,marginBottom: 200, position:"fixed", backgroundColor: theme.palette.inputColor, borderRadius: borderRadius, width: 685, }}
|
style={{ zIndex: 1100, marginTop: -20, marginBottom: 200, position: "fixed", backgroundColor: theme.palette.inputColor, borderRadius: borderRadius, width: 685, }}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
style: {
|
style: {
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -130,28 +135,30 @@ const SearchData = props => {
|
|||||||
type="search"
|
type="search"
|
||||||
color="primary"
|
color="primary"
|
||||||
placeholder="Find Public Apps, Workflows, Documentation..."
|
placeholder="Find Public Apps, Workflows, Documentation..."
|
||||||
value={currentRefinement}
|
value={inputValue}
|
||||||
onKeyDown={keyPressHandler}
|
|
||||||
id="shuffle_search_field"
|
id="shuffle_search_field"
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
if (!searchOpen) {
|
if (inputValue.trim() !== '') {
|
||||||
setSearchOpen(true)
|
setSearchOpen(true);
|
||||||
setTimeout(() => {
|
|
||||||
var tarfield = document.getElementById("shuffle_search_field")
|
|
||||||
//console.log("TARFIELD: ", tarfield)
|
|
||||||
tarfield.focus()
|
|
||||||
}, 250)
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onBlur={(event) => {
|
onBlur={(event) => {
|
||||||
//setTimeout(() => {
|
setSearchOpen(inputValue.trim() !== '')
|
||||||
// setSearchOpen(false)
|
|
||||||
//}, 500)
|
|
||||||
}}
|
}}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
refine(event.currentTarget.value)
|
const newValue = event.target.value;
|
||||||
|
setInputValue(newValue);
|
||||||
|
refine(newValue);
|
||||||
|
if (newValue.trim() !== '') {
|
||||||
|
setSearchOpen(true);
|
||||||
|
} else {
|
||||||
|
setSearchOpen(false);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
onKeyDown={keyPressHandler}
|
||||||
|
inputRef={textFieldRef}
|
||||||
limit={5}
|
limit={5}
|
||||||
|
autoFocus
|
||||||
/>
|
/>
|
||||||
{/*isSearchStalled ? 'My search is stalled' : ''*/}
|
{/*isSearchStalled ? 'My search is stalled' : ''*/}
|
||||||
</form>
|
</form>
|
||||||
@@ -183,8 +190,8 @@ const SearchData = props => {
|
|||||||
const baseImage = <CodeIcon />
|
const baseImage = <CodeIcon />
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card elevation={0} style={{ marginRight: 10,marginTop:50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 75, boxShadows: "none", }}>
|
<Card elevation={0} style={{ marginRight: 10, marginTop: 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 75, boxShadows: "none", }}>
|
||||||
<Typography variant="h6" style={{ margin: "10px 10px 0px 20px", color:"#FF8444", borderBottom: "1px solid", width: 105 }}>
|
<Typography variant="h6" style={{ margin: "10px 10px 0px 20px", color: "#FF8444", borderBottom: "1px solid", width: 105 }}>
|
||||||
Workflows
|
Workflows
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
@@ -234,7 +241,7 @@ const SearchData = props => {
|
|||||||
<Link key={hit.objectID} to={parsedUrl} rel="noopener noreferrer" style={{ textDecoration: "none", color: "white", }} onClick={(event) => {
|
<Link key={hit.objectID} to={parsedUrl} rel="noopener noreferrer" style={{ textDecoration: "none", color: "white", }} onClick={(event) => {
|
||||||
//console.log("CLICK")
|
//console.log("CLICK")
|
||||||
setSearchOpen(true)
|
setSearchOpen(true)
|
||||||
|
setModalOpen(false)
|
||||||
aa('init', {
|
aa('init', {
|
||||||
appId: searchClient.appId,
|
appId: searchClient.appId,
|
||||||
apiKey: searchClient.transporter.queryParameters["x-algolia-api-key"]
|
apiKey: searchClient.transporter.queryParameters["x-algolia-api-key"]
|
||||||
@@ -258,7 +265,6 @@ const SearchData = props => {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
window.open(parsedUrl, '_blank');
|
window.open(parsedUrl, '_blank');
|
||||||
}
|
}
|
||||||
setModalOpen(false)
|
|
||||||
}}>
|
}}>
|
||||||
<ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => {
|
<ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => {
|
||||||
setMouseHoverIndex(index)
|
setMouseHoverIndex(index)
|
||||||
@@ -350,7 +356,7 @@ const SearchData = props => {
|
|||||||
}}>
|
}}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton> */}
|
</IconButton> */}
|
||||||
<Typography variant="h6" style={{ margin: "40px 10px 0px 20px", color:"#FF8444", borderBottom: "1px solid", width: 50 }}>
|
<Typography variant="h6" style={{ margin: "40px 10px 0px 20px", color: "#FF8444", borderBottom: "1px solid", width: 50 }}>
|
||||||
Apps
|
Apps
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
@@ -424,10 +430,9 @@ const SearchData = props => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Link key={hit.objectID} to={parsedUrl} style={{ textDecoration: "none", color: "white", }} onClick={(event) => {
|
<Link key={hit.objectID} to={parsedUrl} style={{ textDecoration: "none", color: "white", }} onClick={(event) => {
|
||||||
console.log("CLICK")
|
|
||||||
setSearchOpen(true)
|
setSearchOpen(true)
|
||||||
setModalOpen(false)
|
|
||||||
|
|
||||||
|
setModalOpen(false)
|
||||||
aa('init', {
|
aa('init', {
|
||||||
appId: searchClient.appId,
|
appId: searchClient.appId,
|
||||||
apiKey: searchClient.transporter.queryParameters["x-algolia-api-key"]
|
apiKey: searchClient.transporter.queryParameters["x-algolia-api-key"]
|
||||||
@@ -513,13 +518,13 @@ const SearchData = props => {
|
|||||||
//console.log(type, hits.length, hits)
|
//console.log(type, hits.length, hits)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card elevation={0} style={{ marginRight: 10,marginTop:50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 470, boxShadows: "none", }}>
|
<Card elevation={0} style={{ marginRight: 10, marginTop: 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 470, boxShadows: "none", }}>
|
||||||
{/* <IconButton style={{ zIndex: 5000, position: "absolute", right: 14, color: "grey" }} onClick={() => {
|
{/* <IconButton style={{ zIndex: 5000, position: "absolute", right: 14, color: "grey" }} onClick={() => {
|
||||||
setSearchOpen(false)
|
setSearchOpen(false)
|
||||||
}}>
|
}}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton> */}
|
</IconButton> */}
|
||||||
<Typography variant="h6" style={{ margin: "10px 10px 0px 20px", color:"#FF8444", borderBottom: "1px solid", width: 152}}>
|
<Typography variant="h6" style={{ margin: "10px 10px 0px 20px", color: "#FF8444", borderBottom: "1px solid", width: 152 }}>
|
||||||
Documentation
|
Documentation
|
||||||
</Typography>
|
</Typography>
|
||||||
{/*
|
{/*
|
||||||
@@ -608,7 +613,7 @@ const SearchData = props => {
|
|||||||
|
|
||||||
console.log("CLICK")
|
console.log("CLICK")
|
||||||
setSearchOpen(true)
|
setSearchOpen(true)
|
||||||
setModalOpen(false)
|
setModalOpen(false)
|
||||||
}}>
|
}}>
|
||||||
<ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => {
|
<ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => {
|
||||||
setMouseHoverIndex(index)
|
setMouseHoverIndex(index)
|
||||||
@@ -636,14 +641,14 @@ const SearchData = props => {
|
|||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const gettingStartData = !searchOpen ? (
|
const gettingStartData = !searchOpen ? (
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
direction="row"
|
direction="row"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
// justify="space-evenly"
|
// justify="space-evenly"
|
||||||
>
|
>
|
||||||
<Grid item xs={6} style={{ alignItems: "center", flexDirection: "row", marginTop: 70, }}>
|
<Grid item xs={6} style={{ alignItems: "center", flexDirection: "row", marginTop: 70, }}>
|
||||||
<List style={{ width: "100%", marginLeft: 10, color: "var(--Paragraph-text, #C8C8C8)" }}>
|
<List style={{ width: "100%", marginLeft: 10, color: "var(--Paragraph-text, #C8C8C8)" }}>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ArticleIcon style={{ marginRight: 10, display: "flex", width: 22 }} />
|
<ArticleIcon style={{ marginRight: 10, display: "flex", width: 22 }} />
|
||||||
@@ -651,28 +656,34 @@ const SearchData = props => {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
<div style={{ marginLeft: 25, }}>
|
<div style={{ marginLeft: 25, }}>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Link onClick={() => { window.location = "/docs"; }} style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
<Link to="/docs" onClick={handleLinkClick} style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
||||||
<Typography variant="body1" style={{ fontSize: 16, }}>Documentation</Typography>
|
<Typography variant="body1" style={{ fontSize: 16, }}>Documentation</Typography>
|
||||||
<KeyboardArrowRightIcon />
|
<KeyboardArrowRightIcon />
|
||||||
</Link>
|
</Link>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Link to="https://github.com/Shuffle/Shuffle/blob/main/.github/install-guide.md" style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
<a
|
||||||
<Typography variant="body1" style={{ fontSize: 16, }}>Onprem Installation</Typography>
|
href="https://github.com/Shuffle/Shuffle/blob/main/.github/install-guide.md"
|
||||||
|
style={{
|
||||||
|
textDecoration: "none",
|
||||||
|
color: "var(--Paragraph-text, #C8C8C8)",
|
||||||
|
display: "flex"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body1" style={{ fontSize: 16 }}>
|
||||||
|
Onprem Installation
|
||||||
|
</Typography>
|
||||||
<KeyboardArrowRightIcon />
|
<KeyboardArrowRightIcon />
|
||||||
</Link>
|
</a>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Link to="/usecases" style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
<Link to="/usecases" onClick={handleLinkClick} style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
||||||
<Typography variant="body1" style={{ fontSize: 16, }}>Explore Usecases</Typography>
|
<Typography variant="body1" style={{ fontSize: 16, }}>Explore Usecases</Typography>
|
||||||
<KeyboardArrowRightIcon />
|
<KeyboardArrowRightIcon />
|
||||||
</Link>
|
</Link>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Link to="/search?tab=workflows" style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
<Link to="/search?tab=workflows" onClick={handleLinkClick} style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
||||||
<Typography variant="body1" style={{ fontSize: 16, }}>Find public workflows</Typography>
|
<Typography variant="body1" style={{ fontSize: 16, }}>Find public workflows</Typography>
|
||||||
<KeyboardArrowRightIcon />
|
<KeyboardArrowRightIcon />
|
||||||
</Link>
|
</Link>
|
||||||
@@ -688,25 +699,25 @@ const SearchData = props => {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
<div style={{ marginLeft: 35 }}>
|
<div style={{ marginLeft: 35 }}>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Link to="/docs/app_creation" style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
<Link to="/docs/app_creation" onClick={handleLinkClick} style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
||||||
<Typography variant="body1" style={{ fontSize: 16, }}>Create Apps</Typography>
|
<Typography variant="body1" style={{ fontSize: 16, }}>Create Apps</Typography>
|
||||||
<KeyboardArrowRightIcon />
|
<KeyboardArrowRightIcon />
|
||||||
</Link>
|
</Link>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Link to="/apps" style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
<Link to="/apps" onClick={handleLinkClick} style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
||||||
<Typography variant="body1" style={{ fontSize: 16, }}>Find Apps</Typography>
|
<Typography variant="body1" style={{ fontSize: 16, }}>Find Apps</Typography>
|
||||||
<KeyboardArrowRightIcon />
|
<KeyboardArrowRightIcon />
|
||||||
</Link>
|
</Link>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Link to="/workflows" style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
<Link to="/workflows" onClick={handleLinkClick} style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
||||||
<Typography variant="body1" style={{ fontSize: 16, }}>Workflows</Typography>
|
<Typography variant="body1" style={{ fontSize: 16, }}>Workflows</Typography>
|
||||||
<KeyboardArrowRightIcon />
|
<KeyboardArrowRightIcon />
|
||||||
</Link>
|
</Link>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Link to="/creators" style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
<Link to="/creators" onClick={handleLinkClick} style={{ textDecoration: "none", color: "var(--Paragraph-text, #C8C8C8)", display: "flex" }}>
|
||||||
<Typography variant="body1" style={{ fontSize: 16, }}>Creator</Typography>
|
<Typography variant="body1" style={{ fontSize: 16, }}>Creator</Typography>
|
||||||
<KeyboardArrowRightIcon />
|
<KeyboardArrowRightIcon />
|
||||||
</Link>
|
</Link>
|
||||||
@@ -721,7 +732,7 @@ const SearchData = props => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
): null
|
) : null
|
||||||
|
|
||||||
const CustomSearchBox = connectSearchBox(SearchBox)
|
const CustomSearchBox = connectSearchBox(SearchBox)
|
||||||
const CustomAppHits = connectHits(AppHits)
|
const CustomAppHits = connectHits(AppHits)
|
||||||
@@ -731,17 +742,17 @@ const SearchData = props => {
|
|||||||
const modalView = (
|
const modalView = (
|
||||||
<div>
|
<div>
|
||||||
<Grid container style={{ display: "contents", }}>
|
<Grid container style={{ display: "contents", }}>
|
||||||
<Grid item xs="auto" style={{ }}>
|
<Grid item xs="auto" style={{}}>
|
||||||
<Index indexName="appsearch">
|
<Index indexName="appsearch">
|
||||||
<CustomAppHits />
|
<CustomAppHits />
|
||||||
</Index>
|
</Index>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs="auto" style={{ }}>
|
<Grid item xs="auto" style={{}}>
|
||||||
<Index indexName="workflows">
|
<Index indexName="workflows">
|
||||||
<CustomWorkflowHits />
|
<CustomWorkflowHits />
|
||||||
</Index>
|
</Index>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs="auto" style={{ }}>
|
<Grid item xs="auto" style={{}}>
|
||||||
<Index indexName="documentation">
|
<Index indexName="documentation">
|
||||||
<CustomDocHits />
|
<CustomDocHits />
|
||||||
</Index>
|
</Index>
|
||||||
@@ -753,14 +764,14 @@ const SearchData = props => {
|
|||||||
return (
|
return (
|
||||||
<div ref={node} style={{ width: "100%", maxWidth: "100%", margin: "auto", }}>
|
<div ref={node} style={{ width: "100%", maxWidth: "100%", margin: "auto", }}>
|
||||||
<InstantSearch searchClient={searchClient} indexName="appsearch" onClick={() => {
|
<InstantSearch searchClient={searchClient} indexName="appsearch" onClick={() => {
|
||||||
|
|
||||||
|
console.log("CLICKED")
|
||||||
}}>
|
}}>
|
||||||
<Configure clickAnalytics />
|
<Configure clickAnalytics />
|
||||||
<CustomSearchBox onClick={() => {
|
<CustomSearchBox />
|
||||||
console.log("Click 2")
|
{modalView}
|
||||||
}}/>
|
|
||||||
{modalView}
|
|
||||||
</InstantSearch>
|
</InstantSearch>
|
||||||
{gettingStartData}
|
{gettingStartData}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
|
|||||||
|
|
||||||
import theme from '../theme.jsx';
|
import theme from '../theme.jsx';
|
||||||
import { useNavigate, Link, useParams } from "react-router-dom";
|
import { useNavigate, Link, useParams } from "react-router-dom";
|
||||||
import SearchBox from "./SearchData.jsx";
|
import SearchBox from "../components/SearchData.jsx";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Chip,
|
Chip,
|
||||||
@@ -91,8 +91,8 @@ const SearchField = props => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isHeader ? <div style={{ display: "flex"}}>
|
{isHeader ? <div style={{ display: "flex"}}>
|
||||||
<DialogTitle style={{ marginTop: 15, marginLeft: 5, color: "var(--Paragraph-text, #C8C8C8)" }} >Search for docs, apps, workflows and more</DialogTitle>
|
<DialogTitle style={{ marginTop: 15, marginLeft: 5, color: "var(--Paragraph-text, #C8C8C8)" }} >Search for Docs, Apps, Workflows and more</DialogTitle>
|
||||||
<Button fullWidth style={{ marginLeft: 470 }} onClick={() => {
|
<Button fullWidth style={{ marginLeft:180, }} onClick={() => {
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
}}><CloseIcon /></Button>
|
}}><CloseIcon /></Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -365,7 +365,6 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: "rgba(255, 132, 68, 1)",
|
color: "rgba(255, 132, 68, 1)",
|
||||||
marginTop: 32,
|
marginTop: 32,
|
||||||
justifyContent: isMobile ? "center" : null,
|
|
||||||
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
||||||
fontWeight: 550,
|
fontWeight: 550,
|
||||||
}}
|
}}
|
||||||
@@ -449,7 +448,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", maxWidth: isCloud ? 470 : isMobile? null: 450, minWidth: isCloud ? 470 : isMobile? null: 450, height: 78, borderRadius: 8, }}>
|
<div style={{ display: "flex", maxWidth: isCloud ? 470 : isMobile? 345: 450, minWidth: isCloud ? 470 : isMobile? null: 450, height: 78, borderRadius: 8, }}>
|
||||||
<ModalView />
|
<ModalView />
|
||||||
<div
|
<div
|
||||||
// variant={isActive === 1 ? "contained" : "outlined"}
|
// variant={isActive === 1 ? "contained" : "outlined"}
|
||||||
@@ -457,7 +456,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
disabled={visualOnly === true}
|
disabled={visualOnly === true}
|
||||||
style={{
|
style={{
|
||||||
margin: isHomePage ? isMobile ? null : 4 : 4 ,
|
margin: isHomePage ? isMobile ? null : 4 : 4 ,
|
||||||
width: "100%",
|
width: isHomePage? isMobile ? null : "100%" : "100%",
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
backgroundColor: isHomePage ? null : theme.palette.inputColor,
|
backgroundColor: isHomePage ? null : theme.palette.inputColor,
|
||||||
@@ -503,31 +502,31 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
<div style={{display: "flex", flex: 1, marginTop: 3, }}>
|
<div style={{display: "flex", flex: 1, marginTop: 3, }}>
|
||||||
{img1 !== undefined && img1 !== "" && srcapp !== undefined && srcapp !== "" ?
|
{img1 !== undefined && img1 !== "" && srcapp !== undefined && srcapp !== "" ?
|
||||||
<Tooltip title={srcapp.replaceAll(":default", "").replaceAll("_", " ").replaceAll(" API", "")} placement="top">
|
<Tooltip title={srcapp.replaceAll(":default", "").replaceAll("_", " ").replaceAll(" API", "")} placement="top">
|
||||||
<span style={srcapp !== undefined && srcapp.includes(":default") ? imagestyleWrapperDefault : imagestyleWrapper}>
|
<div style={srcapp !== undefined && srcapp.includes(":default") ? imagestyleWrapperDefault : imagestyleWrapper}>
|
||||||
<img src={img1} style={srcapp !== undefined && srcapp.includes(":default") ? imagestyleDefault : imagestyle} />
|
<img src={img1} style={srcapp !== undefined && srcapp.includes(":default") ? imagestyleDefault : imagestyle} />
|
||||||
</span>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
:
|
:
|
||||||
<span style={{width: 50, }} />
|
<div style={{width: 50, }} />
|
||||||
}
|
}
|
||||||
{img2 !== undefined && img2 !== "" && dstapp !== undefined && dstapp !== "" ?
|
{img2 !== undefined && img2 !== "" && dstapp !== undefined && dstapp !== "" ?
|
||||||
<Tooltip title={dstapp.replaceAll(":default", "").replaceAll("_", " ").replaceAll(" API", "")} placement="top">
|
<Tooltip title={dstapp.replaceAll(":default", "").replaceAll("_", " ").replaceAll(" API", "")} placement="top">
|
||||||
<span style={{display: "flex", }}>
|
<div style={{display: "flex", }}>
|
||||||
<TrendingFlatIcon style={{ marginTop: 7, }} />
|
<TrendingFlatIcon style={{ marginTop: 7, }} />
|
||||||
<span style={dstapp !== undefined && dstapp.includes(":default") ? imagestyleWrapperDefault : imagestyleWrapper}>
|
<div style={dstapp !== undefined && dstapp.includes(":default") ? imagestyleWrapperDefault : imagestyleWrapper}>
|
||||||
<img src={img2} style={dstapp !== undefined && dstapp.includes(":default") ? imagestyleDefault : imagestyle} />
|
<img src={img2} style={dstapp !== undefined && dstapp.includes(":default") ? imagestyleDefault : imagestyle} />
|
||||||
</span>
|
</div>
|
||||||
</span>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
:
|
:
|
||||||
<span style={{width: 50, }} />
|
<div style={{width: 50, }} />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: 3, marginLeft: 20, }}>
|
<div style={{ flex: 3, marginLeft: 20, }}>
|
||||||
<Typography variant="body1" style={{ marginTop: parsedDescription.length === 0 ? 10 : 0, fontSize: isMobile ? 13 : 16,fontWeight: isHomePage? 600 : null,textTransform: 'capitalize', color: isHomePage ? "var(--White-text, #F1F1F1)" :"rgba(241, 241, 241, 1)"}} >
|
<Typography variant="body1" style={{ marginTop: parsedDescription.length === 0 ? 10 : 0, fontSize: isMobile ? 13 : 16,fontWeight: isHomePage? 600 : null,textTransform: 'capitalize', color: isHomePage ? "var(--White-text, #F1F1F1)" :"rgba(241, 241, 241, 1)"}} >
|
||||||
{parsedTitle}
|
{parsedTitle}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="textSecondary" style={{ fontSize: isMobile ? 10: 16, fontWeight: isHomePage ? 400 : null, textTransform: 'capitalize', marginTop: 0, overflow: "hidden", maxHeight: 21, overflow: "hidden",}} color="rgba(158, 158, 158, 1)">
|
<Typography variant="body2" color="textSecondary" style={{ fontSize: isMobile ? 10: 16, fontWeight: isHomePage ? 400 : null, textTransform: 'capitalize', marginTop: 0, overflow: "hidden", maxHeight: 31,}} color="rgba(158, 158, 158, 1)">
|
||||||
{parsedDescription}
|
{parsedDescription}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ import {
|
|||||||
Visibility as VisibilityIcon,
|
Visibility as VisibilityIcon,
|
||||||
VisibilityOff as VisibilityOffIcon,
|
VisibilityOff as VisibilityOffIcon,
|
||||||
|
|
||||||
|
Flag as FlagIcon,
|
||||||
FmdGood as FmdGoodIcon,
|
FmdGood as FmdGoodIcon,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
|
|
||||||
@@ -1812,7 +1813,7 @@ If you're interested, please let me know a time that works for you, or set up a
|
|||||||
{selectedAuthentication.label})
|
{selectedAuthentication.label})
|
||||||
</span>
|
</span>
|
||||||
<Typography variant="body1" color="textSecondary" style={{marginTop: 10}}>
|
<Typography variant="body1" color="textSecondary" style={{marginTop: 10}}>
|
||||||
You can not see the previous values for an authentication while editing. This is to keep your data secure. You can overwrite one- or multiple fields at a time.
|
You can <b>not</b> see the previous values for an authentication while editing. This is to keep your data secure. You can overwrite one- or multiple fields at a time.
|
||||||
</Typography>
|
</Typography>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
@@ -1844,7 +1845,14 @@ If you're interested, please let me know a time that works for you, or set up a
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
{selectedAuthentication.fields.map((data, index) => {
|
{selectedAuthentication.type === "oauth" || selectedAuthentication.type === "oauth2" || selectedAuthentication.type === "oauth2-app" ?
|
||||||
|
<div>
|
||||||
|
<Typography variant="body1" color="textSecondary" style={{ marginBottom: 0, marginTop: 10 }}>
|
||||||
|
Only the name of the auth can be modified for Oauth2. Please remake the authentication to change the fields like Client ID, Secret, Scopes etc.
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
selectedAuthentication.fields.map((data, index) => {
|
||||||
var fieldname = data.key.replaceAll("_", " ")
|
var fieldname = data.key.replaceAll("_", " ")
|
||||||
if (fieldname.endsWith(" basic")) {
|
if (fieldname.endsWith(" basic")) {
|
||||||
fieldname = fieldname.substring(0, fieldname.length - 6)
|
fieldname = fieldname.substring(0, fieldname.length - 6)
|
||||||
@@ -1914,6 +1922,10 @@ If you're interested, please let me know a time that works for you, or set up a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selectedAuthentication.type === "oauth" || selectedAuthentication.type === "oauth2" || selectedAuthentication.type === "oauth2-app") {
|
||||||
|
selectedAuthentication.fields = []
|
||||||
|
}
|
||||||
|
|
||||||
if (error && fails === authenticationFields.length) {
|
if (error && fails === authenticationFields.length) {
|
||||||
toast("Updating auth with new name only")
|
toast("Updating auth with new name only")
|
||||||
saveAuthentication(selectedAuthentication);
|
saveAuthentication(selectedAuthentication);
|
||||||
@@ -2427,16 +2439,23 @@ If you're interested, please let me know a time that works for you, or set up a
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var regiontag = "eu";
|
||||||
|
if (userdata.region_url !== undefined && userdata.region_url !== null && userdata.region_url.length > 0) {
|
||||||
|
const regionsplit = userdata.region_url.split(".");
|
||||||
|
if (regionsplit.length > 2 && !regionsplit[0].includes("shuffler")) {
|
||||||
|
const namesplit = regionsplit[0].split("/");
|
||||||
|
|
||||||
|
regiontag = namesplit[namesplit.length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const organizationView =
|
const organizationView =
|
||||||
curTab === 0 && selectedOrganization.id !== undefined ? (
|
curTab === 0 && selectedOrganization.id !== undefined ? (
|
||||||
<div style={{ position: "relative" }}>
|
<div style={{ position: "relative" }}>
|
||||||
<div style={{ marginTop: 20, marginBottom: 20 }}>
|
<div style={{ marginTop: 20, marginBottom: 20 }}>
|
||||||
<h2 style={{ display: "inline" }}>Organization overview</h2>
|
<h2 style={{ display: "inline" }}>Organization overview</h2>
|
||||||
<span style={{ marginLeft: 25 }}>
|
<Typography variant="body1" color="textSecondary" style={{ marginLeft: 0}}>
|
||||||
On this page you can configure individual parts of your
|
On this page organization admins can configure organisations, and sub-orgs (MSSP).{" "}
|
||||||
organization.{" "}
|
|
||||||
<a
|
<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
@@ -2445,7 +2464,7 @@ If you're interested, please let me know a time that works for you, or set up a
|
|||||||
>
|
>
|
||||||
Learn more
|
Learn more
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
{selectedOrganization.id === undefined ? (
|
{selectedOrganization.id === undefined ? (
|
||||||
<div
|
<div
|
||||||
@@ -2518,6 +2537,21 @@ If you're interested, please let me know a time that works for you, or set up a
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
</span>
|
</span>
|
||||||
: null}
|
: null}
|
||||||
|
{isCloud ?
|
||||||
|
<Tooltip
|
||||||
|
title={`Organization is in ${regiontag}. Click to change!`}
|
||||||
|
style={{}}
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
style={{ top: -10, right: 50, position: "absolute", }}
|
||||||
|
onClick={() => {
|
||||||
|
toast("Region change is not implemented yet for users. Please contact support.")
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{regiontag}
|
||||||
|
</Avatar>
|
||||||
|
</Tooltip>
|
||||||
|
: null}
|
||||||
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={"Copy Organization ID"}
|
title={"Copy Organization ID"}
|
||||||
@@ -2597,13 +2631,13 @@ If you're interested, please let me know a time that works for you, or set up a
|
|||||||
value={adminTab}
|
value={adminTab}
|
||||||
indicatorColor="primary"
|
indicatorColor="primary"
|
||||||
textColor="secondary"
|
textColor="secondary"
|
||||||
style={{marginTop: 20, }}
|
style={{marginTop: 50, }}
|
||||||
onChange={(event, inputValue) => {
|
onChange={(event, inputValue) => {
|
||||||
const newValue = parseInt(inputValue);
|
const newValue = parseInt(inputValue);
|
||||||
setAdminTab(newValue);
|
setAdminTab(newValue);
|
||||||
|
|
||||||
//const setConfig = (event, inputValue) => {
|
//const setConfig = (event, inputValue) => {
|
||||||
navigate(`/admin?admin_tab=${admin_views[newValue]}`);
|
navigate(`/admin?admin_tab=${admin_views[newValue]}`);
|
||||||
}}
|
}}
|
||||||
aria-label="disabled tabs example"
|
aria-label="disabled tabs example"
|
||||||
>
|
>
|
||||||
@@ -3846,7 +3880,7 @@ If you're interested, please let me know a time that works for you, or set up a
|
|||||||
{data.defined ? (
|
{data.defined ? (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="primary"
|
color="primary"
|
||||||
title="Set in EVERY workflow in the organization"
|
title="Set for EVERY instance of this App being used in this organization"
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -4289,7 +4323,7 @@ If you're interested, please let me know a time that works for you, or set up a
|
|||||||
<div style={{ marginTop: 20, marginBottom: 20 }}>
|
<div style={{ marginTop: 20, marginBottom: 20 }}>
|
||||||
<h2 style={{ display: "inline" }}>Organizations</h2>
|
<h2 style={{ display: "inline" }}>Organizations</h2>
|
||||||
<span style={{ marginLeft: 25 }}>
|
<span style={{ marginLeft: 25 }}>
|
||||||
Global admin: control organizations
|
Control sub organizations (tenants)! {isCloud ? "You can only make a sub organization if you are a customer of shuffle or running a POC of the platform. Please contact support@shuffler.io to try it out." : ""}. <a href="/docs/organizations" target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: theme.palette.primary.main }}>Learn more</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -128,8 +128,8 @@ import Draggable from "react-draggable";
|
|||||||
|
|
||||||
import cytoscapestyle from "../defaultCytoscapeStyle.jsx";
|
import cytoscapestyle from "../defaultCytoscapeStyle.jsx";
|
||||||
|
|
||||||
import { validateJson, GetIconInfo } from "./Workflows.jsx";
|
import { validateJson, GetIconInfo } from "../views/Workflows.jsx";
|
||||||
import { GetParsedPaths } from "./Apps.jsx";
|
import { GetParsedPaths, internalIds, } from "../views/Apps.jsx";
|
||||||
import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx";
|
import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx";
|
||||||
import AuthenticationOauth2 from "../components/Oauth2Auth.jsx";
|
import AuthenticationOauth2 from "../components/Oauth2Auth.jsx";
|
||||||
import ParsedAction from "../components/ParsedAction.jsx";
|
import ParsedAction from "../components/ParsedAction.jsx";
|
||||||
@@ -523,6 +523,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const [_, setUpdate] = useState(""); // Used to force rendring, don't remove
|
const [_, setUpdate] = useState(""); // Used to force rendring, don't remove
|
||||||
|
|
||||||
const [workflowExecutions, setWorkflowExecutions] = React.useState([]);
|
const [workflowExecutions, setWorkflowExecutions] = React.useState([]);
|
||||||
|
const [workflowExecutionCount, setWorkflowExecutionCount] = React.useState(0);
|
||||||
const [defaultEnvironmentIndex, setDefaultEnvironmentIndex] = React.useState(0);
|
const [defaultEnvironmentIndex, setDefaultEnvironmentIndex] = React.useState(0);
|
||||||
const [workflowRecommendations, setWorkflowRecommendations] = React.useState(undefined);
|
const [workflowRecommendations, setWorkflowRecommendations] = React.useState(undefined);
|
||||||
|
|
||||||
@@ -547,6 +548,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
"field_id": "",
|
"field_id": "",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [executionArgumentModalOpen, setExecutionArgumentModalOpen] = React.useState(false);
|
||||||
|
|
||||||
// This should all be set once, not on every iteration
|
// This should all be set once, not on every iteration
|
||||||
// Use states and don't update lol
|
// Use states and don't update lol
|
||||||
const cloudSyncEnabled =
|
const cloudSyncEnabled =
|
||||||
@@ -709,6 +712,33 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getWorkflowExecutionCount = (workflowId) => {
|
||||||
|
fetch(`${globalUrl}/api/v1/workflows/${workflowId}/executions/count`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
credentials: "include",
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status !== 200) {
|
||||||
|
console.log("Status not 200 for workflow execution count: O!");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((responseJson) => {
|
||||||
|
if (responseJson !== undefined) {
|
||||||
|
setWorkflowExecutionCount(responseJson.count || 0);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
toast(error.toString());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getAvailableWorkflows = (trigger_index) => {
|
const getAvailableWorkflows = (trigger_index) => {
|
||||||
fetch(globalUrl + "/api/v1/workflows", {
|
fetch(globalUrl + "/api/v1/workflows", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -992,6 +1022,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
console.log("GOT A RESPONSE??")
|
console.log("GOT A RESPONSE??")
|
||||||
|
getWorkflowExecutionCount(id);
|
||||||
if (responseJson !== undefined && responseJson !== null && responseJson.executions !== undefined && responseJson.executions !== null) {
|
if (responseJson !== undefined && responseJson !== null && responseJson.executions !== undefined && responseJson.executions !== null) {
|
||||||
|
|
||||||
// - means it's opposite
|
// - means it's opposite
|
||||||
@@ -1733,6 +1764,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const executeWorkflow = (executionArgument, startNode, hasSaved) => {
|
const executeWorkflow = (executionArgument, startNode, hasSaved) => {
|
||||||
|
|
||||||
ReactDOM.unstable_batchedUpdates(() => {
|
ReactDOM.unstable_batchedUpdates(() => {
|
||||||
if (hasSaved === false) {
|
if (hasSaved === false) {
|
||||||
setExecutionRequestStarted(true);
|
setExecutionRequestStarted(true);
|
||||||
@@ -1755,6 +1787,41 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setExecutionRequest({})
|
setExecutionRequest({})
|
||||||
stop()
|
stop()
|
||||||
|
|
||||||
|
// FIXME: Check if any node contains $exec in a param
|
||||||
|
// If they do, show a popup asking if they want to execute it without an execution argument, or to use a previous one
|
||||||
|
if (executionArgument === undefined || executionArgument === null || executionArgument.length === 0 && workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) {
|
||||||
|
var foundmissing = false
|
||||||
|
for (let actionkey in workflow.actions) {
|
||||||
|
if (workflow.actions[actionkey].parameters === undefined || workflow.actions[actionkey].parameters === null || workflow.actions[actionkey].parameters.length === 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let paramkey in workflow.actions[actionkey].parameters) {
|
||||||
|
const param = workflow.actions[actionkey].parameters[paramkey]
|
||||||
|
if (param.value === undefined || param.value === null || param.value.length === 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param.value.indexOf("$exec") !== -1) {
|
||||||
|
foundmissing = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundmissing) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("FOUNDMISSING: ", foundmissing)
|
||||||
|
if (foundmissing) {
|
||||||
|
//toast("This workflow contains a node that requires an execution argument. Please provide one.")
|
||||||
|
setExecutionRequestStarted(false)
|
||||||
|
setExecutionArgumentModalOpen(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var curelements = cy.elements();
|
var curelements = cy.elements();
|
||||||
for (let i = 0; i < curelements.length; i++) {
|
for (let i = 0; i < curelements.length; i++) {
|
||||||
curelements[i].addClass("not-executing-highlight");
|
curelements[i].addClass("not-executing-highlight");
|
||||||
@@ -1824,7 +1891,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setExecutionModalOpen(true);
|
setExecutionModalOpen(true);
|
||||||
setExecutionModalView(1);
|
setExecutionModalView(1);
|
||||||
start();
|
start();
|
||||||
navigate(`/workflows/${props.match.params.key}?execution_id=${responseJson.execution_id}`)
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
//toast(error.toString());
|
//toast(error.toString());
|
||||||
@@ -1837,7 +1903,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// This can be used to only show prioritzed ones later
|
// This can be used to only show prioritzed ones later
|
||||||
// Right now, it can prioritize authenticated ones
|
// Right now, it can prioritize authenticated ones
|
||||||
//"Testing",
|
//"Testing",
|
||||||
const internalIds = ["Shuffle Tools", "http", "email"];
|
|
||||||
|
|
||||||
const getAppAuthentication = (reset, updateAction, closeMenu) => {
|
const getAppAuthentication = (reset, updateAction, closeMenu) => {
|
||||||
fetch(globalUrl + "/api/v1/apps/authentication", {
|
fetch(globalUrl + "/api/v1/apps/authentication", {
|
||||||
@@ -2039,8 +2104,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setApps(responseJson);
|
setApps(responseJson);
|
||||||
|
|
||||||
if (isCloud) {
|
if (isCloud) {
|
||||||
setFilteredApps(responseJson.filter((app) => !internalIds.includes(app.name)));
|
setFilteredApps(responseJson.filter((app) => !internalIds.includes(app.name.toLowerCase())));
|
||||||
setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name)));
|
setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name.toLowerCase())));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//setFilteredApps(
|
//setFilteredApps(
|
||||||
@@ -2051,12 +2116,12 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// )
|
// )
|
||||||
//);
|
//);
|
||||||
|
|
||||||
var tmpFiltered = responseJson.filter((app) => !internalIds.includes(app.name))
|
var tmpFiltered = responseJson.filter((app) => !internalIds.includes(app.name.toLowerCase()))
|
||||||
//tmpFiltered = sortByKey(tmpFiltered, "activated")
|
//tmpFiltered = sortByKey(tmpFiltered, "activated")
|
||||||
setFilteredApps(tmpFiltered)
|
setFilteredApps(tmpFiltered)
|
||||||
|
|
||||||
//!(!app.activated && app.generated)
|
//!(!app.activated && app.generated)
|
||||||
setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name)));
|
setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name.toLowerCase())));
|
||||||
}
|
}
|
||||||
|
|
||||||
setAppsLoaded(true)
|
setAppsLoaded(true)
|
||||||
@@ -3785,19 +3850,19 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
return;
|
return;
|
||||||
} else if (data.isDescriptor) {
|
} else if (data.isDescriptor) {
|
||||||
console.log("Can't select descriptor");
|
console.log("Can't select descriptor");
|
||||||
if (data.isTrigger) {
|
if (data.isTrigger) {
|
||||||
console.log("But maybe we can select trigger descriptor? Maybe open execution tab?")
|
console.log("But maybe we can select trigger descriptor? Maybe open execution tab?")
|
||||||
setExecutionModalOpen(true)
|
setExecutionModalOpen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
event.target.unselect();
|
event.target.unselect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.type === undefined) {
|
if (data.type === undefined) {
|
||||||
console.log("No type, automatically setting to action");
|
console.log("No type, automatically setting to action");
|
||||||
data.type = "ACTION"
|
data.type = "ACTION"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.type === "ACTION") {
|
if (data.type === "ACTION") {
|
||||||
setSelectedComment({})
|
setSelectedComment({})
|
||||||
@@ -3924,39 +3989,60 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const tmpAuth = JSON.parse(JSON.stringify(newAppAuth));
|
const tmpAuth = JSON.parse(JSON.stringify(newAppAuth));
|
||||||
//console.log("FOUND AUTH OPTIONS: ", tmpAuth)
|
//console.log("FOUND AUTH OPTIONS: ", tmpAuth)
|
||||||
|
|
||||||
const curappName = curapp.name.toLowerCase()
|
const curappName = curapp.name.toLowerCase()
|
||||||
for (let tmpAuthKey in tmpAuth) {
|
for (let tmpAuthKey in tmpAuth) {
|
||||||
var item = tmpAuth[tmpAuthKey];
|
var item = tmpAuth[tmpAuthKey];
|
||||||
|
|
||||||
const newfields = {};
|
const newfields = {};
|
||||||
if (item.app.name.toLowerCase() !== curappName) {
|
if (item.app.name.toLowerCase() !== curappName) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes list into key:value object
|
// Makes list into key:value object
|
||||||
for (let fieldkey in item.fields) {
|
for (let fieldkey in item.fields) {
|
||||||
if (item.fields[fieldkey] === undefined) {
|
if (item.fields[fieldkey] === undefined) {
|
||||||
console.log("Problem with filterkey in Node select", fieldkey)
|
console.log("Problem with filterkey in Node select", fieldkey)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const filterkey = item.fields[fieldkey]["key"]
|
const filterkey = item.fields[fieldkey]["key"]
|
||||||
if (filterkey === null || filterkey === undefined) {
|
if (filterkey === null || filterkey === undefined) {
|
||||||
console.log("Problem with filterkey 2. Null or undefined 3")
|
console.log("Problem with filterkey 2. Null or undefined 3")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
newfields[filterkey] = item.fields[fieldkey]["value"];
|
newfields[filterkey] = item.fields[fieldkey]["value"];
|
||||||
}
|
}
|
||||||
|
|
||||||
item.fields = newfields;
|
item.fields = newfields;
|
||||||
if (item.app.name.toLowerCase() === curappName) {
|
if (item.app.name.toLowerCase() === curappName) {
|
||||||
authenticationOptions.push(item);
|
authenticationOptions.push(item);
|
||||||
if (item.id === findAuthId) {
|
if (item.id === findAuthId) {
|
||||||
curaction.selectedAuthentication = item;
|
curaction.selectedAuthentication = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("OPTIONS: ", authenticationOptions)
|
||||||
|
// Find with authenticationOption (authenticationOptions) has the highest .edited time. In this index, set the "last_modified" to true
|
||||||
|
|
||||||
|
var latesttime = 0
|
||||||
|
var latestindex = -1
|
||||||
|
|
||||||
|
for (var i = 0; i < authenticationOptions.length; i++) {
|
||||||
|
const authopt = authenticationOptions[i]
|
||||||
|
console.log("AUTHOPT: ", authopt)
|
||||||
|
|
||||||
|
if (authopt.edited > latesttime) {
|
||||||
|
latesttime = authopt.edited
|
||||||
|
latestindex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("LATEST INDEX: ", latestindex)
|
||||||
|
if (latestindex !== -1) {
|
||||||
|
authenticationOptions[latestindex].last_modified = true
|
||||||
|
}
|
||||||
|
|
||||||
curaction.authentication = authenticationOptions;
|
curaction.authentication = authenticationOptions;
|
||||||
if (
|
if (
|
||||||
@@ -7468,26 +7554,26 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
const tmpAuth = JSON.parse(JSON.stringify(appAuthentication));
|
const tmpAuth = JSON.parse(JSON.stringify(appAuthentication));
|
||||||
for (let authkey in tmpAuth) {
|
for (let authkey in tmpAuth) {
|
||||||
if (authkey === undefined) {
|
if (authkey === undefined) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = tmpAuth[authkey];
|
var item = tmpAuth[authkey];
|
||||||
const newfields = {};
|
const newfields = {};
|
||||||
for (let fieldkey in item.fields) {
|
for (let fieldkey in item.fields) {
|
||||||
if (item.fields[fieldkey] === undefined) {
|
if (item.fields[fieldkey] === undefined) {
|
||||||
console.log("Problem with filterkey in Node select", fieldkey)
|
console.log("Problem with filterkey in Node select", fieldkey)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const filterkey = item.fields[fieldkey]["key"]
|
const filterkey = item.fields[fieldkey]["key"]
|
||||||
if (filterkey === null || filterkey === undefined) {
|
if (filterkey === null || filterkey === undefined) {
|
||||||
console.log("Problem with filterkey 2. Null or undefined 3")
|
console.log("Problem with filterkey 2. Null or undefined 3")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
newfields[filterkey] = item.fields[fieldkey]["value"];
|
newfields[filterkey] = item.fields[fieldkey]["value"];
|
||||||
}
|
}
|
||||||
|
|
||||||
item.fields = newfields;
|
item.fields = newfields;
|
||||||
if (item.app.id === app.id || item.app.name === app.name) {
|
if (item.app.id === app.id || item.app.name === app.name) {
|
||||||
@@ -7734,9 +7820,9 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const [visibleApps, setVisibleApps] = React.useState(
|
const [visibleApps, setVisibleApps] = React.useState(
|
||||||
Array.prototype.concat.apply(
|
Array.prototype.concat.apply(
|
||||||
prioritizedApps,
|
prioritizedApps,
|
||||||
filteredApps.filter((innerapp) => !internalIds.includes(innerapp.id)),
|
filteredApps.filter((innerapp) => !internalIds.includes(innerapp.id.toLowerCase()))
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
|
|
||||||
var delay = -75
|
var delay = -75
|
||||||
var runDelay = false
|
var runDelay = false
|
||||||
@@ -7983,7 +8069,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setVisibleApps(
|
setVisibleApps(
|
||||||
prioritizedApps.concat(
|
prioritizedApps.concat(
|
||||||
filteredApps.filter(
|
filteredApps.filter(
|
||||||
(innerapp) => !internalIds.includes(innerapp.id)
|
(innerapp) => !internalIds.includes(innerapp.id.toLowerCase())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -9159,6 +9245,133 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: theme.palette.inputColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Makes a list of items the user can choose from based on previous runs
|
||||||
|
var availableArguments = []
|
||||||
|
if (executionArgumentModalOpen && workflowExecutions.length > 0) {
|
||||||
|
for (let executionKey in workflowExecutions) {
|
||||||
|
if (availableArguments.length > 5) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
const execution = workflowExecutions[executionKey]
|
||||||
|
if (execution.execution_argument === undefined || execution.execution_argument === null || execution.execution_argument.length < 2) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (availableArguments.includes(execution.execution_argument)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
availableArguments.push(execution.execution_argument)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const executionArgumentModal =
|
||||||
|
<Dialog
|
||||||
|
PaperComponent={PaperComponent}
|
||||||
|
disableEnforceFocus={true}
|
||||||
|
hideBackdrop={true}
|
||||||
|
disableBackdropClick={true}
|
||||||
|
style={{ pointerEvents: "none" }}
|
||||||
|
PaperComponent={PaperComponent}
|
||||||
|
aria-labelledby="draggable-dialog-title"
|
||||||
|
open={executionArgumentModalOpen}
|
||||||
|
PaperProps={{
|
||||||
|
style: {
|
||||||
|
padding: 30,
|
||||||
|
pointerEvents: "auto",
|
||||||
|
color: "white",
|
||||||
|
minWidth: isMobile ? "90%" : 800,
|
||||||
|
border: theme.palette.defaultBorder,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClose={() => {
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
title="Close window"
|
||||||
|
placement="top"
|
||||||
|
style={{ zIndex: 10011 }}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
style={{ zIndex: 5000, position: "absolute", top: 34, right: 34 }}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setExecutionArgumentModalOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CloseIcon style={{ color: "white" }} />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<DialogTitle id="draggable-dialog-title" style={{ cursor: "move", }}>
|
||||||
|
<span style={{ color: "white" }}>Please provide an execution argument</span>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography variant="body1" color="textSecondary">
|
||||||
|
At least one node in this workflow requires an execution argument. Please select one below, or provide a custom one in the text field next to the run button.
|
||||||
|
</Typography>
|
||||||
|
{/*
|
||||||
|
<div style={{marginTop: 10, }}>
|
||||||
|
<Tooltip
|
||||||
|
color="primary"
|
||||||
|
title="An argument to be used for execution. This is a variable available to every node in your workflow."
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
id="execution_argument_input_field"
|
||||||
|
style={theme.palette.textFieldStyle}
|
||||||
|
disabled={workflow.public}
|
||||||
|
color="secondary"
|
||||||
|
placeholder={"Execution Argument"}
|
||||||
|
defaultValue={executionText}
|
||||||
|
onBlur={(e) => {
|
||||||
|
setExecutionText(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
*/}
|
||||||
|
|
||||||
|
<Divider style={{marginTop: 10, marginBottom: 20, }}/>
|
||||||
|
{availableArguments.length > 0 ?
|
||||||
|
<div>
|
||||||
|
<Typography variant="body1" style={{}}>
|
||||||
|
Previously used arguments:
|
||||||
|
</Typography>
|
||||||
|
{availableArguments.map((data) => {
|
||||||
|
return (
|
||||||
|
<Paper style={{ padding: 10, marginTop: 10, backgroundColor: theme.palette.platformColor, maxHeight: 70, overflow: "auto", cursor: "pointer", position: "relative", }}
|
||||||
|
onClick={() => {
|
||||||
|
setExecutionText(data)
|
||||||
|
executeWorkflow(data, workflow.start, lastSaved);
|
||||||
|
setExecutionArgumentModalOpen(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{height: "100%", width: 2, backgroundColor: "rgba(255, 255, 255, 0.5)", position: "absolute", left: 0, top: 0}} />
|
||||||
|
<Typography variant="body1" color="textSecondary">
|
||||||
|
{data}
|
||||||
|
</Typography>
|
||||||
|
</Paper>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
: null}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
onClick={() => {
|
||||||
|
executeWorkflow(" ", workflow.start, lastSaved);
|
||||||
|
setExecutionArgumentModalOpen(false);
|
||||||
|
}}
|
||||||
|
style={{ marginTop: 20, marginBottom: 20 }}
|
||||||
|
>
|
||||||
|
Run anyway
|
||||||
|
</Button>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
const aiQueryModal =
|
const aiQueryModal =
|
||||||
<Dialog
|
<Dialog
|
||||||
PaperComponent={PaperComponent}
|
PaperComponent={PaperComponent}
|
||||||
@@ -13490,9 +13703,54 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
variant="body2"
|
variant="body2"
|
||||||
>
|
>
|
||||||
{workflow.errors.slice(0,3).map((error) => {
|
{workflow.errors.slice(0,3).map((error) => {
|
||||||
|
// Loop through each word, and if it matches "Action <name> " then replace it with a link to the action
|
||||||
|
var colornext = false
|
||||||
|
const newerror = error === undefined || error == null ? "" : error.split(" ").map((word) => {
|
||||||
|
if (colornext) {
|
||||||
|
colornext = false
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
style={{color: "#f85a3e", cursor: "pointer"}}
|
||||||
|
onClick={() => {
|
||||||
|
console.log("Clicked action: ", word)
|
||||||
|
|
||||||
|
// Find it in cytoscape
|
||||||
|
if (cy === undefined || cy === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const foundnode = cy.nodes().filter((node) => {
|
||||||
|
return node.data().label === word
|
||||||
|
})
|
||||||
|
|
||||||
|
if (foundnode === undefined || foundnode === null || foundnode.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Found node: ", foundnode)
|
||||||
|
cy.elements().unselect()
|
||||||
|
foundnode[0].select()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{word}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (word.toLowerCase() === "action") {
|
||||||
|
colornext = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return word + " "
|
||||||
|
})
|
||||||
|
|
||||||
|
if (newerror === undefined || newerror === null || newerror === "") {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
- {error}
|
- {newerror}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
@@ -13635,7 +13893,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{workflow.public ? (
|
{workflow.public || userdata.support == true ? (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="secondary"
|
color="secondary"
|
||||||
title="Download workflow"
|
title="Download workflow"
|
||||||
@@ -14811,7 +15069,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
>
|
>
|
||||||
<h2 style={{ color: "rgba(255,255,255,0.5)" }}>
|
<h2 style={{ color: "rgba(255,255,255,0.5)" }}>
|
||||||
<DirectionsRunIcon style={{ marginRight: 10 }} />
|
<DirectionsRunIcon style={{ marginRight: 10 }} />
|
||||||
All Workflow Runs
|
All Workflow Runs: { workflowExecutionCount }
|
||||||
</h2>
|
</h2>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@@ -14819,7 +15077,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
placement="left-start"
|
placement="left-start"
|
||||||
style={{ zIndex: 10010 }}
|
style={{ zIndex: 10010 }}
|
||||||
>
|
>
|
||||||
<a href={`/workflows/debug?workflow_id=${workflow.id}`} style={{textDecoration: "none", }}>
|
<a target="_blank" href={`/workflows/debug?workflow_id=${workflow.id}`} style={{textDecoration: "none", }}>
|
||||||
<Button
|
<Button
|
||||||
color="secondary"
|
color="secondary"
|
||||||
style={{marginLeft: 50, maxHeight: 30, marginTop: 20, }}
|
style={{marginLeft: 50, maxHeight: 30, marginTop: 20, }}
|
||||||
@@ -14839,7 +15097,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
<CachedIcon style={{ marginRight: 10 }} />
|
<CachedIcon style={{ marginRight: 10 }} />
|
||||||
Refresh Runs
|
Refresh Runs
|
||||||
</Button>
|
</Button>
|
||||||
<Divider
|
<Divider
|
||||||
style={{
|
style={{
|
||||||
@@ -17910,6 +18168,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
{newView}
|
{newView}
|
||||||
<VariablesModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
|
<VariablesModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
|
||||||
<ExecutionVariableModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
|
<ExecutionVariableModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
|
||||||
|
{executionArgumentModal}
|
||||||
{aiQueryModal}
|
{aiQueryModal}
|
||||||
{conditionsModal}
|
{conditionsModal}
|
||||||
{authenticationModal}
|
{authenticationModal}
|
||||||
|
|||||||
@@ -1527,6 +1527,10 @@ const AppCreator = (defaultprops) => {
|
|||||||
in: "query",
|
in: "query",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (parameter.example !== undefined && parameter.example !== null) {
|
||||||
|
tmpaction.example = parameter.example
|
||||||
|
}
|
||||||
|
|
||||||
if (parameter.required === undefined) {
|
if (parameter.required === undefined) {
|
||||||
tmpaction.required = false;
|
tmpaction.required = false;
|
||||||
}
|
}
|
||||||
@@ -2289,7 +2293,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const methodname = item.method.toLowerCase()
|
const methodname = item.method.toLowerCase()
|
||||||
if (methodname === "post" || methodname === "put" || methodname === "patch") {
|
if (methodname === "post" || methodname === "put" || methodname === "patch" || methodname === "delete") {
|
||||||
if (
|
if (
|
||||||
item.body !== undefined &&
|
item.body !== undefined &&
|
||||||
item.body !== null &&
|
item.body !== null &&
|
||||||
@@ -3432,11 +3436,11 @@ const AppCreator = (defaultprops) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const deletePathQuery = (index) => {
|
const deletePathQuery = (index) => {
|
||||||
console.log("Should delete index: ", index)
|
console.log("Should delete index: ", index)
|
||||||
var tmpqueries = JSON.parse(JSON.stringify(urlPathQueries))
|
var tmpqueries = JSON.parse(JSON.stringify(urlPathQueries))
|
||||||
tmpqueries.splice(index, 1)
|
tmpqueries.splice(index, 1)
|
||||||
|
|
||||||
console.log("Queries: ", tmpqueries)
|
console.log("Queries: ", tmpqueries)
|
||||||
setUrlPathQueries(tmpqueries);
|
setUrlPathQueries(tmpqueries);
|
||||||
|
|
||||||
if (updater === "deleteupdater") {
|
if (updater === "deleteupdater") {
|
||||||
@@ -4316,6 +4320,8 @@ const AppCreator = (defaultprops) => {
|
|||||||
|
|
||||||
setCurrentAction(data);
|
setCurrentAction(data);
|
||||||
setCurrentActionMethod(data.method);
|
setCurrentActionMethod(data.method);
|
||||||
|
|
||||||
|
console.log("QUERIES: ", data.queries)
|
||||||
setUrlPathQueries(data.queries);
|
setUrlPathQueries(data.queries);
|
||||||
setUrlPath(data.url);
|
setUrlPath(data.url);
|
||||||
setActionsModalOpen(true);
|
setActionsModalOpen(true);
|
||||||
|
|||||||
+204
-58
@@ -88,6 +88,7 @@ export const FixName = (name) => {
|
|||||||
return newAppname;
|
return newAppname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Takes input of e.g. $node.data.#.asd and a matching value from a json blob
|
// Takes input of e.g. $node.data.#.asd and a matching value from a json blob
|
||||||
// Returns
|
// Returns
|
||||||
export const FindJsonPath = (path, inputdata) => {
|
export const FindJsonPath = (path, inputdata) => {
|
||||||
@@ -157,6 +158,8 @@ export const FindJsonPath = (path, inputdata) => {
|
|||||||
return inputdata
|
return inputdata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const internalIds = ["shuffle tools", "http", "email"];
|
||||||
|
|
||||||
// Parses JSON data into keys that can be used everywhere :)
|
// Parses JSON data into keys that can be used everywhere :)
|
||||||
// Reverse of this is FindJsonPath
|
// Reverse of this is FindJsonPath
|
||||||
export const GetParsedPaths = (inputdata, basekey) => {
|
export const GetParsedPaths = (inputdata, basekey) => {
|
||||||
@@ -270,7 +273,7 @@ export const GetParsedPaths = (inputdata, basekey) => {
|
|||||||
|
|
||||||
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240")
|
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240")
|
||||||
const Apps = (props) => {
|
const Apps = (props) => {
|
||||||
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
|
const { globalUrl, isLoggedIn, isLoaded, userdata, serverside, } = props;
|
||||||
|
|
||||||
//const [workflows, setWorkflows] = React.useState([]);
|
//const [workflows, setWorkflows] = React.useState([]);
|
||||||
const baseRepository = "https://github.com/frikky/shuffle-apps";
|
const baseRepository = "https://github.com/frikky/shuffle-apps";
|
||||||
@@ -304,6 +307,8 @@ const Apps = (props) => {
|
|||||||
const [cursearch, setCursearch] = React.useState("");
|
const [cursearch, setCursearch] = React.useState("");
|
||||||
const [sharingConfiguration, setSharingConfiguration] = React.useState("you");
|
const [sharingConfiguration, setSharingConfiguration] = React.useState("you");
|
||||||
const [downloadBranch, setDownloadBranch] = React.useState("master");
|
const [downloadBranch, setDownloadBranch] = React.useState("master");
|
||||||
|
const [creatorProfile, setCreatorProfile] = React.useState({});
|
||||||
|
const [contact, setContact] = React.useState("");
|
||||||
|
|
||||||
const [isDropzone, setIsDropzone] = React.useState(false);
|
const [isDropzone, setIsDropzone] = React.useState(false);
|
||||||
const upload = React.useRef(null);
|
const upload = React.useRef(null);
|
||||||
@@ -324,6 +329,40 @@ const Apps = (props) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getUserProfile = (username) => {
|
||||||
|
if (serverside === true || !isCloud) {
|
||||||
|
setCreatorProfile({})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(`${globalUrl}/api/v1/users/creators/${username}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
credentials: "include",
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status !== 200) {
|
||||||
|
console.log("Status not 200 for WORKFLOW EXECUTION :O!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((responseJson) => {
|
||||||
|
if (responseJson.success !== false) {
|
||||||
|
setCreatorProfile(responseJson);
|
||||||
|
} else {
|
||||||
|
setCreatorProfile({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
setCreatorProfile({})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (apps.length <= 0 && firstrequest) {
|
if (apps.length <= 0 && firstrequest) {
|
||||||
document.title = "Shuffle - Apps";
|
document.title = "Shuffle - Apps";
|
||||||
@@ -441,6 +480,12 @@ const Apps = (props) => {
|
|||||||
setFilteredApps(privateapps);
|
setFilteredApps(privateapps);
|
||||||
if (privateapps.length > 0) {
|
if (privateapps.length > 0) {
|
||||||
if (selectedApp.id === undefined || selectedApp.id === null) {
|
if (selectedApp.id === undefined || selectedApp.id === null) {
|
||||||
|
if (privateapps[0].owner !== undefined && privateapps[0].owner !== null) {
|
||||||
|
getUserProfile(privateapps[0].owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
setContact(privateapps[0].contact_info)
|
||||||
|
|
||||||
setSelectedApp(privateapps[0]);
|
setSelectedApp(privateapps[0]);
|
||||||
setSharingConfiguration(privateapps[0].sharing === true ? "public" : "you")
|
setSharingConfiguration(privateapps[0].sharing === true ? "public" : "you")
|
||||||
}
|
}
|
||||||
@@ -646,6 +691,13 @@ const Apps = (props) => {
|
|||||||
style={paperAppStyle}
|
style={paperAppStyle}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (selectedApp.id !== data.id) {
|
if (selectedApp.id !== data.id) {
|
||||||
|
|
||||||
|
if (data.owner !== undefined && data.owner !== null) {
|
||||||
|
getUserProfile(data.owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
setContact(data.contact_info)
|
||||||
|
|
||||||
data.name = newAppname;
|
data.name = newAppname;
|
||||||
setSelectedApp(data);
|
setSelectedApp(data);
|
||||||
setSharingConfiguration(data.sharing === true ? "public" : "you")
|
setSharingConfiguration(data.sharing === true ? "public" : "you")
|
||||||
@@ -882,7 +934,7 @@ const Apps = (props) => {
|
|||||||
Activate App
|
Activate App
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
<Tooltip title={"Delete app"}>
|
<Tooltip title={"Delete app (confirm box will show)"}>
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
component="label"
|
component="label"
|
||||||
@@ -1114,7 +1166,7 @@ const Apps = (props) => {
|
|||||||
|
|
||||||
{activateButton}
|
{activateButton}
|
||||||
|
|
||||||
{ /* editNewButton === null && */ }
|
{ /* editNewButton === null && */ }
|
||||||
|
|
||||||
{canEditApp ? (
|
{canEditApp ? (
|
||||||
<div>
|
<div>
|
||||||
@@ -1127,35 +1179,12 @@ const Apps = (props) => {
|
|||||||
{editNewButton}
|
{editNewButton}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{selectedApp.tags !== undefined && selectedApp.tags !== null ? (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "inline-block",
|
|
||||||
marginLeft: 15,
|
|
||||||
float: "right",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{selectedApp.tags.map((tag, index) => {
|
|
||||||
if (index >= 3) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
{canEditApp
|
||||||
<Chip
|
? (
|
||||||
key={index}
|
<div style={{ marginTop: 15, display: "flex", }}>
|
||||||
style={chipStyle}
|
|
||||||
variant="outlined"
|
|
||||||
label={tag}
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{canEditApp
|
|
||||||
? (
|
|
||||||
<div style={{ marginTop: 15 }}>
|
|
||||||
{/*<p><b>ID:</b> {selectedApp.id}</p>*/}
|
{/*<p><b>ID:</b> {selectedApp.id}</p>*/}
|
||||||
|
|
||||||
<b style={{ marginRight: 15 }}>Sharing </b>
|
<b style={{ marginRight: 15 }}>Sharing </b>
|
||||||
<Select
|
<Select
|
||||||
value={sharingConfiguration}
|
value={sharingConfiguration}
|
||||||
@@ -1209,8 +1238,117 @@ const Apps = (props) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
|
{isCloud && (selectedApp.sharing === true || selectedApp.public === true || creatorProfile.github_avatar !== undefined) && !internalIds.includes(selectedApp.name.toLowerCase()) ?
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
component="label"
|
||||||
|
color="primary"
|
||||||
|
onClick={() => {
|
||||||
|
const tmpurl = new URL(window.location.href);
|
||||||
|
const searchParams = tmpurl.searchParams;
|
||||||
|
const queryID = searchParams.get("queryID");
|
||||||
|
|
||||||
|
if (queryID !== undefined && queryID !== null) {
|
||||||
|
aa("init", {
|
||||||
|
appId: "JNSS5CFDZZ",
|
||||||
|
apiKey: "db08e40265e2941b9a7d8f644b6e5240",
|
||||||
|
});
|
||||||
|
|
||||||
|
const timestamp = new Date().getTime();
|
||||||
|
aa("sendEvents", [
|
||||||
|
{
|
||||||
|
eventType: "conversion",
|
||||||
|
eventName: "Public App Activated",
|
||||||
|
index: "appsearch",
|
||||||
|
objectIDs: [selectedApp.id],
|
||||||
|
timestamp: timestamp,
|
||||||
|
queryID: queryID,
|
||||||
|
userToken:
|
||||||
|
userdata === undefined ||
|
||||||
|
userdata === null ||
|
||||||
|
userdata.id === undefined
|
||||||
|
? "unauthenticated"
|
||||||
|
: userdata.id,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
console.log("No query to handle when activating");
|
||||||
|
}
|
||||||
|
|
||||||
|
activateApp(selectedApp.id, true)
|
||||||
|
}}
|
||||||
|
style={{ height: 35, marginTop: 0, marginLeft: 10, }}
|
||||||
|
>
|
||||||
|
Deactivate
|
||||||
|
</Button>
|
||||||
|
: null}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
<div style={{display: "flex", }}>
|
||||||
|
{isCloud && Object.getOwnPropertyNames(creatorProfile).length !== 0 && creatorProfile.github_avatar !== undefined && creatorProfile.github_avatar !== null ?
|
||||||
|
<div style={{ display: "flex", marginTop: 15, }}>
|
||||||
|
<IconButton
|
||||||
|
color="primary"
|
||||||
|
style={{ padding: 0, marginRight: 10 }}
|
||||||
|
aria-controls="simple-menu"
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={(event) => {
|
||||||
|
//setAnchorElAvatar(event.currentTarget);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
to={`/creators/${creatorProfile.github_username}`}
|
||||||
|
style={{ textDecoration: "none", color: "#f86a3e" }}
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
style={{ height: 30, width: 30 }}
|
||||||
|
alt={contact.name}
|
||||||
|
src={creatorProfile.github_avatar}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</IconButton>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
color="textSecondary"
|
||||||
|
style={{ color: "" }}
|
||||||
|
>
|
||||||
|
Shared by{" "}
|
||||||
|
<Link
|
||||||
|
to={`/creators/${creatorProfile.github_username}`}
|
||||||
|
style={{ textDecoration: "none", color: "#f86a3e" }}
|
||||||
|
>
|
||||||
|
{creatorProfile.github_username}
|
||||||
|
</Link>
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
: null}
|
||||||
|
{selectedApp.tags !== undefined && selectedApp.tags !== null ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginLeft: 20,
|
||||||
|
marginTop: 15,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{selectedApp.tags.map((tag, index) => {
|
||||||
|
if (index >= 3) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Chip
|
||||||
|
key={index}
|
||||||
|
style={chipStyle}
|
||||||
|
variant="outlined"
|
||||||
|
label={tag}
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
{/*<p><b>Owner:</b> {selectedApp.owner}</p>*/}
|
{/*<p><b>Owner:</b> {selectedApp.owner}</p>*/}
|
||||||
{selectedApp.privateId !== undefined &&
|
{selectedApp.privateId !== undefined &&
|
||||||
selectedApp.privateId.length > 0 ? (
|
selectedApp.privateId.length > 0 ? (
|
||||||
@@ -1666,37 +1804,45 @@ const Apps = (props) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const activateApp = (appid, refresh) => {
|
const activateApp = (appid, refresh) => {
|
||||||
fetch(globalUrl + "/api/v1/apps/" + appid + "/activate", {
|
const appExists = userdata.active_apps !== undefined && userdata.active_apps !== null && userdata.active_apps.includes(appid)
|
||||||
method: 'GET',
|
const url = appExists ? `${globalUrl}/api/v1/apps/${appid}/deactivate` : `${globalUrl}/api/v1/apps/${appid}/activate`
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
fetch(url, {
|
||||||
'Accept': 'application/json',
|
method: 'GET',
|
||||||
},
|
headers: {
|
||||||
credentials: "include",
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
},
|
||||||
|
credentials: "include",
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status !== 200) {
|
||||||
|
console.log("Failed to deactivate")
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json()
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((responseJson) => {
|
||||||
if (response.status !== 200) {
|
if (responseJson.success === false) {
|
||||||
console.log("Failed to activate")
|
toast("Failed to activate the app")
|
||||||
}
|
} else {
|
||||||
|
//toast("App activated for your organization! Refresh the page to use the app.")
|
||||||
|
if (appExists) {
|
||||||
|
toast("App deactivated for your organization! Existing workflows with the app will continue to work.")
|
||||||
|
} else {
|
||||||
|
toast("App activated for your organization!")
|
||||||
|
}
|
||||||
|
|
||||||
return response.json()
|
if (refresh === true) {
|
||||||
})
|
getApps()
|
||||||
.then((responseJson) => {
|
|
||||||
if (responseJson.success === false) {
|
|
||||||
toast("Failed to activate the app")
|
|
||||||
} else {
|
|
||||||
toast("App activated for your organization! Refresh the page to use the app.")
|
|
||||||
|
|
||||||
if (refresh === true) {
|
|
||||||
getApps()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.catch(error => {
|
})
|
||||||
//toast(error.toString())
|
.catch(error => {
|
||||||
console.log("Activate app error: ", error.toString())
|
//toast(error.toString())
|
||||||
});
|
console.log("Deactivate app error: ", error.toString())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -675,11 +675,13 @@ func deployWorker(image string, identifier string, env []string, executionReques
|
|||||||
|
|
||||||
createdPod, err := clientset.CoreV1().Pods("shuffle").Create(context.Background(), pod, metav1.CreateOptions{})
|
createdPod, err := clientset.CoreV1().Pods("shuffle").Create(context.Background(), pod, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error creating pod: %v\n", err)
|
log.Printf("[ERROR] Failed creating pod: %v", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[INFO] Created pod %q in namespace %q\n", createdPod.Name, createdPod.Namespace)
|
log.Printf("[INFO] Created pod %q in namespace %q\n", createdPod.Name, createdPod.Namespace)
|
||||||
} else {
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Binds is the actual "-v" volume.
|
// Binds is the actual "-v" volume.
|
||||||
// Max 20% CPU every second
|
// Max 20% CPU every second
|
||||||
@@ -839,9 +841,6 @@ func deployWorker(image string, identifier string, env []string, executionReques
|
|||||||
log.Printf("[INFO][%s] New Worker created. Environment %s: docker logs %s", executionRequest.ExecutionId, environment, cont.ID)
|
log.Printf("[INFO][%s] New Worker created. Environment %s: docker logs %s", executionRequest.ExecutionId, environment, cont.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1039,11 +1038,16 @@ func getOrborusStats(ctx context.Context) shuffle.OrborusStats {
|
|||||||
Timestamp: time.Now().Unix(),
|
Timestamp: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Returning for now due to this causing network congestion
|
||||||
|
// and database fillup. The backend api also has it disabled.
|
||||||
|
return newStats
|
||||||
|
|
||||||
// Disable orborus stats
|
// Disable orborus stats
|
||||||
if os.Getenv("SHUFFLE_STATS_DISABLED") == "true" {
|
if os.Getenv("SHUFFLE_STATS_DISABLED") == "true" {
|
||||||
return newStats
|
return newStats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if swarmConfig == "run" || swarmConfig == "swarm" {
|
if swarmConfig == "run" || swarmConfig == "swarm" {
|
||||||
newStats.Swarm = true
|
newStats.Swarm = true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user