Moved over cache view and admin tracker features

This commit is contained in:
Frikky
2024-03-27 15:17:05 +01:00
parent 16ef8082d2
commit c50b84036e
8 changed files with 157 additions and 57 deletions
+11 -7
View File
@@ -49,15 +49,19 @@ DOCKER_API_VERSION=1.40
# Orborus/Proxy configurations # Orborus/Proxy configurations
HTTP_PROXY= HTTP_PROXY=
HTTPS_PROXY= HTTPS_PROXY=
SHUFFLE_PASS_WORKER_PROXY=TRUE # Decides if proxy configurations should be passed to workers or not SHUFFLE_PASS_WORKER_PROXY=TRUE
SHUFFLE_PASS_APP_PROXY=TRUE # Decides if proxy configurations should be passed to apps or not. Requires SHUFFLE_PASS_WORKER_PROXY=true SHUFFLE_PASS_APP_PROXY=TRUE
SHUFFLE_INTERNAL_HTTP_PROXY= # Used to differentiate proxies for shuffle internal vs external traffic SHUFFLE_INTERNAL_HTTP_PROXY=
SHUFFLE_INTERNAL_HTTPS_PROXY= SHUFFLE_INTERNAL_HTTPS_PROXY=
TZ=Europe/Amsterdam # Timezone-handler in Orborus, Worker and Apps # Timezone-handler in Orborus, Worker and Apps
ORBORUS_CONTAINER_NAME= # Used to FIND the containername. cgroup v2: issue 501 TZ=Europe/Amsterdam
SHUFFLE_ORBORUS_STARTUP_DELAY= # Used for setting up a startup delay for Orborus # Used to FIND the containername. cgroup v2: issue 501
ORBORUS_CONTAINER_NAME=
# Used for setting up a startup delay for Orborus
SHUFFLE_ORBORUS_STARTUP_DELAY=
SHUFFLE_SKIPSSL_VERIFY=true SHUFFLE_SKIPSSL_VERIFY=true
IS_KUBERNETES=false # Used for controlling if the environment should run in kubernetes or not # Used for controlling if the environment should run in kubernetes or not
IS_KUBERNETES=false
#SHUFFLE_BASE_IMAGE_NAME=shuffle #SHUFFLE_BASE_IMAGE_NAME=shuffle
#SHUFFLE_BASE_IMAGE_REGISTRY=ghcr.io #SHUFFLE_BASE_IMAGE_REGISTRY=ghcr.io
+18 -18
View File
@@ -93,26 +93,26 @@ const CacheView = (props) => {
}, },
credentials: "include", credentials: "include",
}) })
.then((response) => { .then((response) => {
if (response.status !== 200) { if (response.status !== 200) {
console.log("Status not 200 for apps :O!"); console.log("Status not 200 for list cache :O!");
return; return;
} }
return response.json(); return response.json();
}) })
.then((responseJson) => { .then((responseJson) => {
if (responseJson.success === true) { if (responseJson.success === true) {
setListCache(responseJson.keys); setListCache(responseJson.keys);
} }
if (responseJson.cursor !== undefined && responseJson.cursor !== null && responseJson.cursor !== "") { if (responseJson.cursor !== undefined && responseJson.cursor !== null && responseJson.cursor !== "") {
setCacheCursor(responseJson.cursor); setCacheCursor(responseJson.cursor);
} }
}) })
.catch((error) => { .catch((error) => {
toast(error.toString()); toast(error.toString());
}); });
}; };
// const getCacheList = (orgId) => { // const getCacheList = (orgId) => {
+12
View File
@@ -155,9 +155,21 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho
.then(() => { .then(() => {
// Log out anyway // Log out anyway
removeCookie("session_token", {path: "/"}) removeCookie("session_token", {path: "/"})
removeCookie("__session", {path: "/"})
removeCookie("_session", {path: "/"})
removeCookie("session_token", {path: "/"}) removeCookie("session_token", {path: "/"})
removeCookie("__session", {path: "/"})
removeCookie("_session", {path: "/"})
removeCookie("session_token", {path: "/"}) removeCookie("session_token", {path: "/"})
removeCookie("__session", {path: "/"})
removeCookie("_session", {path: "/"})
removeCookie("session_token", {path: "/"}) removeCookie("session_token", {path: "/"})
removeCookie("__session", {path: "/"})
removeCookie("_session", {path: "/"})
window.location.pathname = "/" window.location.pathname = "/"
}) })
.catch(error => { .catch(error => {
+1 -1
View File
@@ -1155,7 +1155,7 @@ const Header = (props) => {
userdata.app_execution_usage === undefined || userdata.app_execution_usage === undefined ||
userdata.app_execution_usage < 1000 ? null : ( userdata.app_execution_usage < 1000 ? null : (
<Tooltip <Tooltip
title={`Amount of executions left: ${userdata.app_execution_usage} / ${userdata.app_execution_limit}. When the limit is reached, you can still use Shuffle normally, but your Workflow triggers may stop working. Reach out to support@shuffler.io to extend this limit.`} title={`Amount of App Runs used: ${userdata.app_execution_usage} / ${userdata.app_execution_limit}. When the limit is reached, you can still use Shuffle normally, but your Workflow triggers will stop workflows from starting. Reach out to support@shuffler.io to extend this limit.`}
> >
<div <div
style={{ style={{
+28 -2
View File
@@ -86,6 +86,7 @@ import {
AutoFixHigh as AutoFixHighIcon, AutoFixHigh as AutoFixHighIcon,
Circle as CircleIcon, Circle as CircleIcon,
SquareFoot as SquareFootIcon, SquareFoot as SquareFootIcon,
Storage as StorageIcon,
} from '@mui/icons-material'; } from '@mui/icons-material';
const useStyles = makeStyles({ const useStyles = makeStyles({
@@ -1063,7 +1064,6 @@ const ParsedAction = (props) => {
} }
var helperText = "" var helperText = ""
//console.log("DATA: ", name, value)
if (name.includes("url")) { if (name.includes("url")) {
if (value.includes("localhost") || value.includes("127.0.0.1")) { if (value.includes("localhost") || value.includes("127.0.0.1")) {
helperText = "Can't use localhost. Please change to your external IP." helperText = "Can't use localhost. Please change to your external IP."
@@ -1364,6 +1364,13 @@ const ParsedAction = (props) => {
} }
} }
var showCacheConfig = false
if (data.name === "key" && selectedAction.name.includes("cache") && selectedAction.app_name === "Shuffle Tools") {
// Show a key popout button
showCacheConfig = true
}
var disabled = false; var disabled = false;
var rows = "3"; var rows = "3";
var openApiHelperText = "This is an OpenAPI specific field"; var openApiHelperText = "This is an OpenAPI specific field";
@@ -1614,10 +1621,14 @@ const ParsedAction = (props) => {
setExpansionModalOpen(true) setExpansionModalOpen(true)
//setcodedata(data.value) //setcodedata(data.value)
var parsedvalue = data.value
if (parsedvalue === undefined || parsedvalue === null) {
parsedvalue = ""
}
setEditorData({ setEditorData({
"name": data.name, "name": data.name,
"value": data.value, "value": parsedvalue,
"field_number": count, "field_number": count,
"actionlist": actionlist, "actionlist": actionlist,
"field_id": clickedFieldId, "field_id": clickedFieldId,
@@ -2484,6 +2495,21 @@ const ParsedAction = (props) => {
: :
null} null}
{showCacheConfig === true ?
<Tooltip
color="primary"
title={"Explore your keys in Datastore"}
placement="top"
>
<a href="/admin?tab=cache" target="_blank" style={{textDecoration: "none"}}>
<StorageIcon style={{
color: "#f85a3e",
marginRight: 10,
}}/>
</a>
</Tooltip>
: null}
<div <div
style={{ style={{
flex: "10", flex: "10",
+37 -8
View File
@@ -572,8 +572,10 @@ const CodeEditor = (props) => {
const highlight_variables = (value) => { const highlight_variables = (value) => {
if (value === undefined || value === null || value.length === 0) { if (value === undefined || value === null || value.length === 0) {
setMarkers([])
return return
} }
// var session = localcodedata.getSession(); // var session = localcodedata.getSession();
//var code_lines = localcodedata.split('\n') //var code_lines = localcodedata.split('\n')
var code_lines = value.split('\n') var code_lines = value.split('\n')
@@ -589,11 +591,11 @@ const CodeEditor = (props) => {
var new_occurences = variable_occurence.filter((occurrence) => occurrence[0]); var new_occurences = variable_occurence.filter((occurrence) => occurrence[0]);
variable_occurence = new_occurences variable_occurence = new_occurences
var dollar_occurence = []; var dollar_occurence = [];
for (let ch = 0; ch < current_code_line.length; ch++) { for (let ch = 0; ch < current_code_line.length; ch++) {
if (current_code_line[ch] === '$' && (ch === 0)) { //if (current_code_line[ch] === '$' && (ch === 0)) {
if (current_code_line[ch] === '$') {
dollar_occurence.push(ch); dollar_occurence.push(ch);
} }
} }
@@ -607,9 +609,6 @@ const CodeEditor = (props) => {
console.log("Error in color highlighting list: ", e); console.log("Error in color highlighting list: ", e);
} }
//console.log("Variable occurences: ", variable_occurence)
//console.log("Dollar occurences: ", dollar_occurence)
try { try {
if (variable_occurence.length === 0) { if (variable_occurence.length === 0) {
//value.markText({line:i, ch:0}, {line:i, ch:code_lines[i].length-1}, {"css": "background-color: #282828; border-radius: 0px; color: #b8bb26"}) //value.markText({line:i, ch:0}, {line:i, ch:code_lines[i].length-1}, {"css": "background-color: #282828; border-radius: 0px; color: #b8bb26"})
@@ -619,8 +618,10 @@ const CodeEditor = (props) => {
for (let occ = 0; occ < variable_occurence.length; occ++) { for (let occ = 0; occ < variable_occurence.length; occ++) {
const fixedVariable = fixVariable(variable_occurence[occ]) const fixedVariable = fixVariable(variable_occurence[occ])
var correctVariable = availableVariables.includes(fixedVariable.toLowerCase()) var correctVariable = availableVariables.includes(fixedVariable.toLowerCase())
var startCh = dollar_occurence[occ] var startCh = dollar_occurence[occ]
var endCh = dollar_occurence[occ] + dollar_occurence_len[occ] var endCh = dollar_occurence[occ] + dollar_occurence_len[occ]
newMarkers.push({ newMarkers.push({
startRow: i, startRow: i,
startCol: startCh, startCol: startCh,
@@ -629,13 +630,17 @@ const CodeEditor = (props) => {
className: correctVariable ? "good-marker" : "bad-marker", className: correctVariable ? "good-marker" : "bad-marker",
type: "text", type: "text",
}) })
setMarkers(newMarkers)
} }
setMarkers(newMarkers)
} catch (e) { } catch (e) {
console.log("Error in color highlighting: ", e); console.log("Error in color highlighting: ", e);
} }
} }
setMarkers(newMarkers)
}; };
const replaceVariables = (swapVariable) => { const replaceVariables = (swapVariable) => {
@@ -927,6 +932,18 @@ const CodeEditor = (props) => {
// Define a custom completer for the Ace Editor
const customVariables = availableVariables
const customCompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
callback(null, customVariables.map((variable) => ({
caption: variable,
value: variable,
meta: 'custom',
})));
}
}
return ( return (
<Dialog <Dialog
aria-labelledby="draggable-code-modal" aria-labelledby="draggable-code-modal"
@@ -1495,7 +1512,13 @@ const CodeEditor = (props) => {
theme="gruvbox" theme="gruvbox"
height={isFileEditor ? 450 : 550} height={isFileEditor ? 450 : 550}
width={isFileEditor ? 650 : "100%"} width={isFileEditor ? 650 : "100%"}
markers={markers} markers={markers}
highlightActiveLine={false}
enableBasicAutocompletion={true}
completers={[customCompleter]}
style={{ style={{
wordBreak: "break-word", wordBreak: "break-word",
marginTop: 0, marginTop: 0,
@@ -1513,7 +1536,7 @@ const CodeEditor = (props) => {
setCurrentLine(cursorPosition.row) setCurrentLine(cursorPosition.row)
findIndex(cursorPosition.row, cursorPosition.column) findIndex(cursorPosition.row, cursorPosition.column)
//highlight_variables(value) highlight_variables(localcodedata)
//console.log("VALUE CURSOR: ", value) //console.log("VALUE CURSOR: ", value)
}} }}
onChange={(value, editor) => { onChange={(value, editor) => {
@@ -1528,7 +1551,12 @@ const CodeEditor = (props) => {
enableBasicAutocompletion: true, enableBasicAutocompletion: true,
enableLiveAutocompletion: true, enableLiveAutocompletion: true,
enableSnippets: true, enableSnippets: true,
useWorker: false showLineNumbers: true,
tabSize: 2,
wrap: true,
useWorker: false,
enableBasicAutocompletion: [customCompleter],
}} }}
// options={options} // options={options}
/> />
@@ -1688,6 +1716,7 @@ const CodeEditor = (props) => {
</Typography> </Typography>
</div> </div>
} }
{executionResult.errors !== undefined && executionResult.errors !== null && executionResult.errors.length > 0 ? {executionResult.errors !== undefined && executionResult.errors !== null && executionResult.errors.length > 0 ?
<Typography variant="body2" style={{maxHeight: 100, overflow: "auto", color: "#f85a3e",}}> <Typography variant="body2" style={{maxHeight: 100, overflow: "auto", color: "#f85a3e",}}>
Errors ({executionResult.errors.length}): {executionResult.errors.join("\n")} Errors ({executionResult.errors.length}): {executionResult.errors.join("\n")}
+2 -4
View File
@@ -4586,19 +4586,17 @@ If you're interested, please let me know a time that works for you, or set up a
foundIndex = userdata.priorities.findIndex(prio => prio.name.includes("CPU") && prio.active === true) foundIndex = userdata.priorities.findIndex(prio => prio.name.includes("CPU") && prio.active === true)
if (foundIndex >= 0 && userdata.priorities[foundIndex].name.endsWith(environment.Name)) { if (foundIndex >= 0 && userdata.priorities[foundIndex].name.endsWith(environment.Name)) {
showCPUAlert = true showCPUAlert = true
} }
} }
//console.log("Show CPU alert: ", showCPUAlert)
const queueSize = environment.queue !== undefined && environment.queue !== null ? environment.queue < 0 ? 0 : environment.queue > 1000 ? ">1000" : environment.queue : 0 const queueSize = environment.queue !== undefined && environment.queue !== null ? environment.queue < 0 ? 0 : environment.queue > 1000 ? ">1000" : environment.queue : 0
return ( return (
<span key={index}> <span key={index}>
<ListItem key={index} style={{ backgroundColor: bgColor, marginLeft: 0, }}> <ListItem key={index} style={{ backgroundColor: bgColor, marginLeft: 0, }}>
<ListItemText <ListItemText
primary={environment.run_type === "cloud" ? primary={environment.run_type === "cloud" || environment.name === "Cloud" ?
<Tooltip title="Cloud" placement="top"> <Tooltip title="Cloud" placement="top">
<CloudIcon style={{ color: "rgba(255,255,255,0.8)" }} /> <CloudIcon style={{ color: "rgba(255,255,255,0.8)" }} />
</Tooltip> </Tooltip>
+48 -17
View File
@@ -3212,9 +3212,7 @@ const AngularWorkflow = (defaultprops) => {
) { ) {
toast("This edge can't be edited."); toast("This edge can't be edited.");
} else { } else {
//console.log("DATA: ", event.target.data())
const destinationId = event.target.data("target"); const destinationId = event.target.data("target");
//console.log("DATA: ", event.target.data())
const curaction = workflow.actions.find((a) => a.id === destinationId); const curaction = workflow.actions.find((a) => a.id === destinationId);
//console.log("ACTION: ", curaction) //console.log("ACTION: ", curaction)
if (curaction !== undefined && curaction !== null) { if (curaction !== undefined && curaction !== null) {
@@ -7608,6 +7606,11 @@ const AngularWorkflow = (defaultprops) => {
} }
} }
// Hiding since March 2024
if (trigger.trigger_type === "EMAIL") {
return null
}
const imagesize = isMobile ? 40 : trigger.large_image.includes("svg") ? 80 : 80 const imagesize = isMobile ? 40 : trigger.large_image.includes("svg") ? 80 : 80
var imageline = trigger.large_image.length === 0 ? <img alt="" style={{ borderRadius: theme.palette.borderRadius, width: isMobile ? 40 : 80, pointerEvents: "none" }} /> var imageline = trigger.large_image.length === 0 ? <img alt="" style={{ borderRadius: theme.palette.borderRadius, width: isMobile ? 40 : 80, pointerEvents: "none" }} />
: :
@@ -7999,7 +8002,6 @@ const AngularWorkflow = (defaultprops) => {
for (let nodekey in foundnodes) { for (let nodekey in foundnodes) {
const curnode = foundnodes[nodekey] const curnode = foundnodes[nodekey]
if (curnode.data.environment !== undefined && curnode.data.environment !== null && curnode.data.environment.length > 0) { if (curnode.data.environment !== undefined && curnode.data.environment !== null && curnode.data.environment.length > 0) {
console.log("Found environment: ", curnode.data.environment)
parsedEnvironments = curnode.data.environment parsedEnvironments = curnode.data.environment
break break
} }
@@ -8007,7 +8009,6 @@ const AngularWorkflow = (defaultprops) => {
} }
} }
console.log("Discovered environment: ", parsedEnvironments)
const newAppData = { const newAppData = {
name: app.actions[actionIndex].name, name: app.actions[actionIndex].name,
label: actionLabel, label: actionLabel,
@@ -9537,7 +9538,7 @@ const AngularWorkflow = (defaultprops) => {
var availableArguments = [] var availableArguments = []
if (executionArgumentModalOpen && workflowExecutions.length > 0) { if (executionArgumentModalOpen && workflowExecutions.length > 0) {
for (let executionKey in workflowExecutions) { for (let executionKey in workflowExecutions) {
if (availableArguments.length > 5) { if (availableArguments.length > 2) {
break break
} }
@@ -16184,7 +16185,6 @@ const AngularWorkflow = (defaultprops) => {
color="primary" color="primary"
style={{ float: "right", marginTop: 20, marginLeft: 10 }} style={{ float: "right", marginTop: 20, marginLeft: 10 }}
onClick={() => { onClick={() => {
//console.log("DATA: ", executionData);
executeWorkflow( executeWorkflow(
executionData.execution_argument, executionData.execution_argument,
executionData.start, executionData.start,
@@ -16443,20 +16443,34 @@ const AngularWorkflow = (defaultprops) => {
: yellow; : yellow;
var imgSrc = curapp === undefined ? "" : curapp.large_image; var imgSrc = curapp === undefined ? "" : curapp.large_image;
if ( if (imgSrc.length === 0 && workflow.actions !== undefined && workflow.actions !== null) {
imgSrc.length === 0 &&
workflow.actions !== undefined &&
workflow.actions !== null
) {
// Look for the node in the workflow // Look for the node in the workflow
const action = workflow.actions.find( const action = workflow.actions.find(
(action) => action.id === data.action.id (action) => action.id === data.action.id
); )
if (action !== undefined && action !== null) { if (action !== undefined && action !== null) {
imgSrc = action.large_image; imgSrc = action.large_image;
} }
} }
if (imgSrc.length === 0 && cy !== undefined && cy !== null) {
const foundnode = cy.getElementById(data.action.id)
if (foundnode !== undefined && foundnode !== null && foundnode.length > 0) {
// FIXME: Find image from cytoscape action
} else {
for (let actionkey in workflow.actions) {
if (workflow.actions[actionkey].app_name === data.action.app_name || workflow.actions[actionkey].id === data.action.id || workflow.actions[actionkey].label === data.action.label || workflow.actions[actionkey].name === data.action.name) {
if (workflow.actions[actionkey].large_image !== undefined && workflow.actions[actionkey].large_image !== null && workflow.actions[actionkey].large_image.length > 0) {
imgSrc = workflow.actions[actionkey].large_image
break
}
}
}
}
}
var actionimg = var actionimg =
curapp === null ? null : ( curapp === null ? null : (
<img <img
@@ -16507,11 +16521,7 @@ const AngularWorkflow = (defaultprops) => {
} }
} }
if ( if (data.action.app_name === "Shuffle Tools" && data.action.id !== undefined && cy !== undefined) {
data.action.app_name === "Shuffle Tools" &&
data.action.id !== undefined &&
cy !== undefined
) {
const nodedata = cy.getElementById(data.action.id).data(); const nodedata = cy.getElementById(data.action.id).data();
if (nodedata !== undefined && nodedata !== null && nodedata.fillstyle === "linear-gradient") { if (nodedata !== undefined && nodedata !== null && nodedata.fillstyle === "linear-gradient") {
var imgStyle = { var imgStyle = {
@@ -16954,6 +16964,18 @@ const AngularWorkflow = (defaultprops) => {
} }
} }
if (result.status === 401) {
return "Authentication failed (401). The URL or auth key is wrong. Check the body of the result for more information."
}
if (result.status === 403) {
return "Authorization failed (403). The API user most likely doesn't have the correct permissions. Check the body of the result for more information."
}
if (result.status === 400) {
return "The queries or data sent to the API is most likely wrong (400). Check the body of the result for more information."
}
// Validate and check for newlines // Validate and check for newlines
if (result.success !== false) { if (result.success !== false) {
@@ -16984,6 +17006,11 @@ const AngularWorkflow = (defaultprops) => {
return "You can't use localhost in apps. Use the external ip or url of the server instead" return "You can't use localhost in apps. Use the external ip or url of the server instead"
} }
if (result.status !== 200 && stringjson.includes("192.168") || stringjson.includes("172.16") || stringjson.includes("10.0")) {
return "Consider whether your Orborus environment can connect to a local IP or not."
}
if (stringjson.includes("connectionerror")) { if (stringjson.includes("connectionerror")) {
if (stringjson.includes("kms")) { if (stringjson.includes("kms")) {
return "KMS authentication failed. Check your notifications for more details." return "KMS authentication failed. Check your notifications for more details."
@@ -16996,6 +17023,10 @@ const AngularWorkflow = (defaultprops) => {
return "Execution loading failed. Reload the execution by closing it and clicking it again" return "Execution loading failed. Reload the execution by closing it and clicking it again"
} }
if (isCloud && stringjson.toLowerCase().includes("timeout error")) {
return "Run this workflow in a local environment to increase the timeout. Go to https://shuffler.io/admin?tab=environments to create an environment to connect to"
}
return "" return ""
} }