Syncing up with cloud files

This commit is contained in:
Frikky
2024-04-18 04:10:34 +02:00
parent c50b84036e
commit bf601e3e1f
21 changed files with 3791 additions and 2388 deletions
+2 -2
View File
@@ -51,8 +51,8 @@ HTTP_PROXY=
HTTPS_PROXY=
SHUFFLE_PASS_WORKER_PROXY=TRUE
SHUFFLE_PASS_APP_PROXY=TRUE
SHUFFLE_INTERNAL_HTTP_PROXY=
SHUFFLE_INTERNAL_HTTPS_PROXY=
SHUFFLE_INTERNAL_HTTP_PROXY=NOPROXY
SHUFFLE_INTERNAL_HTTPS_PROXY=NOPROXY
# Timezone-handler in Orborus, Worker and Apps
TZ=Europe/Amsterdam
# Used to FIND the containername. cgroup v2: issue 501
+32
View File
@@ -58,3 +58,35 @@ code {
color: white !important;
opacity: 0.6;
}
/* Style for checkbox */
.ais-RefinementList-checkbox {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
width: 16px;
height: 16px;
border: 1px solid #595b5e;
border-radius: 4px;
background-color: #27292d;
cursor: pointer;
flex-shrink: 0;
}
.ais-RefinementList-checkbox:checked {
background-color: rgb(248, 103, 67) !important;
border-color: rgb(248, 103, 67) !important;
width: 16px;
height: 16px;
}
.ais-RefinementList-checkbox:checked::before {
content: "\2714";
display: block;
width: 100%;
height: 100%;
text-align: center;
line-height: 18px;
color: #fff;
font-size: 14px;
}
+6 -2
View File
@@ -936,7 +936,7 @@ const AppFramework = (props) => {
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
if (response.status !== 200 || response.status !== 202) {
console.log("Failed to activate")
}
@@ -944,7 +944,11 @@ const AppFramework = (props) => {
})
.then((responseJson) => {
if (responseJson.success === false) {
toast("Failed to activate the app")
var msgString = "Failed to activate the app"
if (responseJson.reason !== undefined) {
msgString += ": " + responseJson.reason
}
toast(msgString)
} else {
//toast("App activated for your organization! Refresh the page to use the app.")
}
@@ -603,10 +603,10 @@ const ConfigureWorkflow = (props) => {
.then((responseJson) => {
if (responseJson.success === false) {
if (responseJson.reason !== undefined) {
toast("Failed to activate the app: "+responseJson.reason);
} else {
toast("Failed to activate the app");
}
toast("Failed to activate the app: "+responseJson.reason);
} else {
toast("Failed to activate the app");
}
} else {
toast("App activated for your organization!");
}
+16 -18
View File
@@ -59,7 +59,7 @@ const Files = (props) => {
const [downloadFolder, setDownloadFolder] = React.useState("translation_standards");
//const alert = useAlert();
const allowedFileTypes = ["txt", "py", "yaml", "yml","json", "html", "js", "csv", "log", "eml", "msg", "md", "xml", "sh", "bat", "ps1", "psm1", "psd1", "ps1xml", "pssc", "psc1"]
const allowedFileTypes = ["txt", "py", "yaml", "yml","json", "html", "js", "csv", "log", "eml", "msg", "md", "xml", "sh", "bat", "ps1", "psm1", "psd1", "ps1xml", "pssc", "psc1", "response"]
var upload = "";
const handleKeyDown = (event) => {
@@ -395,8 +395,6 @@ const Files = (props) => {
setTimeout(() => {
getFiles();
}, 1500);
console.log(responseJson);
})
.catch((error) => {
toast(error.toString());
@@ -759,21 +757,21 @@ const Files = (props) => {
{renderTextBox && <TextField
onKeyPress={(event)=>{
handleKeyDown(event);
}}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
placeholder="File category name"
required
margin="dense"
defaultValue={""}
autoFocus
/>}</div>
onKeyPress={(event)=>{
handleKeyDown(event);
}}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
placeholder="File category name"
required
margin="dense"
defaultValue={""}
autoFocus
/>}</div>
<ShuffleCodeEditor
isCloud={isCloud}
+5
View File
@@ -891,6 +891,11 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho
const namesplit = regionsplit[0].split("/")
regiontag = namesplit[namesplit.length - 1]
if (regiontag === "california") {
regiontag = "us"
} else if (regiontag === "frankfurt") {
regiontag = "fr"
}
}
}
+19 -14
View File
@@ -551,10 +551,19 @@ const Header = (props) => {
handleClose();
}}
>
<BusinessIcon style={{ marginRight: 5 }} /> Admin
<BusinessIcon style={{ marginRight: 5 }} /> Organisation
</MenuItem>
</Link>
<Divider />
<Link to="/settings" style={hrefStyle}>
<MenuItem
onClick={(event) => {
handleClose();
}}
>
<SettingsIcon style={{ marginRight: 5 }} /> Account
</MenuItem>
</Link>
<Divider style={{marginTop: 10, marginBottom: 10, }} />
<Link to="/docs" style={hrefStyle}>
<MenuItem
onClick={(event) => {
@@ -584,7 +593,6 @@ const Header = (props) => {
<LightbulbIcon style={{ marginRight: 5 }} /> Use Cases
</MenuItem>
</Link>
<Divider />
<Link to={`/creators/${userdata.public_username}`} style={hrefStyle}>
<MenuItem
onClick={(event) => {
@@ -594,16 +602,7 @@ const Header = (props) => {
<EmojiObjectsIcon style={{ marginRight: 5 }} /> Creator page
</MenuItem>
</Link>
<Link to="/settings" style={hrefStyle}>
<MenuItem
onClick={(event) => {
handleClose();
}}
>
<SettingsIcon style={{ marginRight: 5 }} /> Settings
</MenuItem>
</Link>
<Divider />
<Divider style={{marginTop: 10, marginBottom: 10, }}/>
<MenuItem
style={{ color: "white" }}
onClick={(event) => {
@@ -617,7 +616,7 @@ const Header = (props) => {
<Divider style={{marginBottom: 10, }}/>
<Typography variant="body2" color="textSecondary" align="center" style={{marginTop: 5, marginBottom: 5,}}>
Version: 1.3.3
Version: 1.3.4
</Typography>
</Menu>
</span>
@@ -1052,6 +1051,12 @@ const Header = (props) => {
const namesplit = regionsplit[0].split("/");
regiontag = namesplit[namesplit.length - 1];
if (regiontag === "california") {
regiontag = "us"
} else if (regiontag === "frankfurt") {
regiontag = "fr"
}
}
}
+1
View File
@@ -172,6 +172,7 @@ const OrgHeader = (props) => {
: theme.palette.inputColor,
maxWidth: 174,
maxHeight: 174,
borderRadius: theme.shape.borderRadius,
}}
onClick={() => {
upload.click();
+155 -54
View File
@@ -164,6 +164,7 @@ const ParsedAction = (props) => {
expansionModalOpen,
setExpansionModalOpen,
apps,
setEditorData,
setcodedata,
setAiQueryModalOpen,
@@ -178,6 +179,8 @@ const ParsedAction = (props) => {
const [autoCompleting, setAutocompleting] = React.useState(false);
const isIntegration = selectedAction.app_id === "integration"
useEffect(() => {
if (setLastSaved !== undefined) {
setLastSaved(false)
@@ -1087,29 +1090,113 @@ const ParsedAction = (props) => {
var authWritten = false;
return (
<div style={{ marginTop: hideExtraTypes ? 10 : 30 }}>
<Tooltip
color="secondary"
title={"Click to learn more about this action"}
placement="top"
{isIntegration ?
apps !== undefined && apps !== null && apps.length > 0 ?
<div style={{display: "flex", }}>
{apps.map((app, appIndex) => {
if (app.categories === undefined || app.categories === null || app.categories.length === 0) {
return null
}
var found = false
var actionname = selectedAction.name.toLowerCase()
if (actionname === "email") {
actionname = "communication"
}
for (var key in app.categories) {
if (app.categories[key].toLowerCase() !== actionname) {
continue
}
found = true
break
}
if (!found) {
return null
}
var isAppSelected = false
const paramIndex = selectedAction.parameters.findIndex((param) => param.name === "app_name")
if (paramIndex > -1) {
// Check the actual value and if it's the same
if (selectedAction.parameters[paramIndex].value === app.name) {
isAppSelected = true
}
}
return (
<div onClick={() => {
selectedAction.large_image = app.large_image
/*
if (cy !== undefined) {
const foundnode = cy.getElementById(selectedAction.id)
if (foundnode !== undefined && foundnode !== null) {
foundnode.data("large_image", app.large_image)
}
}
*/
if (paramIndex === -1) {
console.log("Couldn't find app_name parameter")
selectedAction.parameters.push({
name: "app_name",
value: app.name,
autocompleted: false,
})
} else {
selectedAction.parameters[paramIndex].value = app.name
}
setSelectedAction(selectedAction)
setUpdate(Math.random())
}}>
<Tooltip title={app.name.replace("_", " ", -1)} placement="top">
<img
src={app.large_image}
style={{
width: 35,
height: 35,
marginRight: 5,
borderRadius: 5,
cursor: "pointer",
border: isAppSelected ? "3px solid #86c142" : "2px solid rgba(255,255,255,0.6)",
}} />
</Tooltip>
</div>
)
})}
</div>
: null
:
<Tooltip
color="secondary"
title={"Click to learn more about this action"}
placement="top"
>
<Button
variant="text"
color="secondary"
style={{justifyContent: "flex-start", textAlign: "left", textTransform: "none", width: "100%",}}
fullWidth
disabled={selectedAction.description === undefined || selectedAction.description === null || selectedAction.description.length === 0}
onClick={() => {
setHiddenDescription(!hiddenDescription)
}}
>
<Button
variant="text"
color="secondary"
style={{justifyContent: "flex-start", textAlign: "left", textTransform: "none", width: "100%",}}
fullWidth
disabled={selectedAction.description === undefined || selectedAction.description === null || selectedAction.description.length === 0}
onClick={() => {
setHiddenDescription(!hiddenDescription)
}}
>
<b>Parameters</b>
</Button>
</Tooltip>
{selectedAction.template === true && selectedAction.matching_actions !== undefined && selectedAction.matching_actions !== null && selectedAction.matching_actions.length > 0 ?
<div>
<Typography variant="body1">
Select an app you want to use
</Typography>
<b>Parameters</b>
</Button>
</Tooltip>
}
{selectedAction.template === true && selectedAction.matching_actions !== undefined && selectedAction.matching_actions !== null && selectedAction.matching_actions.length > 0 ?
<div>
<Typography variant="body1">
Select an app you want to use
</Typography>
<Autocomplete
id="template_action_search"
autoHighlight
@@ -1235,11 +1322,16 @@ const ParsedAction = (props) => {
</Typography>
</div>
) : null}
{selectedActionParameters.map((data, count) => {
if (data.variant === "") {
data.variant = "STATIC_VALUE";
}
if (isIntegration && data.name === "app_name") {
return null
}
// selectedAction.selectedAuthentication = e.target.value
// selectedAction.authentication_id = e.target.value.id
if (
@@ -1288,7 +1380,7 @@ const ParsedAction = (props) => {
var staticcolor = "inherit";
var actioncolor = "inherit";
var varcolor = "inherit";
var multiline;
var multiline
if (
data.multiline !== undefined &&
data.multiline !== null &&
@@ -1297,6 +1389,11 @@ const ParsedAction = (props) => {
multiline = true;
}
// make data.value from array to comma separated string if it is an array
if (data.value !== undefined && data.value !== null && Array.isArray(data.value)) {
data.value = data.value.join(",")
}
if (
data.value !== undefined &&
data.value !== null &&
@@ -2003,6 +2100,13 @@ const ParsedAction = (props) => {
changeActionParameter(e, count, data);
}
var multi = false
if (selectedActionParameters[count].multiselect !== undefined && selectedActionParameters[count].multiselect !== null && selectedActionParameters[count].multiselect === true) {
multi = true
selectedActionParameters[count].value = selectedActionParameters[count].value.split(",")
}
datafield = (
<Select
MenuProps={{
@@ -2012,10 +2116,13 @@ const ParsedAction = (props) => {
style: {
},
}}
multiple={multi}
value={selectedActionParameters[count].value}
fullWidth
id={"rightside_field_" + count}
onChange={(e) => {
console.log("MULTI SELECT: ", multi, e.target.value)
changeActionParameter(e, count, data);
setUpdate(Math.random());
}}
@@ -2029,11 +2136,13 @@ const ParsedAction = (props) => {
{parsedoptions.map(
(data, index) => {
const split_data = data.split("||");
var viewed_data = data;
var viewed_data = data
if (split_data.length > 1) {
viewed_data = split_data[0];
viewed_data = split_data[0]
}
viewed_data = (viewed_data.charAt(0).toUpperCase() + viewed_data.slice(1)).replaceAll("_", " ")
return (
<MenuItem
key={data}
@@ -2774,9 +2883,11 @@ const ParsedAction = (props) => {
}
// Gets the most important actions first
const renderedActionOptions = deduplicateByName((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"))).sort(sortByCategoryLabel))
const renderedActionOptions = deduplicateByName((
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"))
).sort(sortByCategoryLabel))
var baselabel = selectedAction.label;
return (
@@ -3000,16 +3111,16 @@ const ParsedAction = (props) => {
</Tooltip>
*/}
{selectedApp.versions !== null &&
selectedApp.versions !== undefined &&
selectedApp.versions.length > 1 ? (
selectedApp.versions !== undefined &&
selectedApp.versions.length > 1 ? (
<Select
MenuProps={{
disableScrollLock: true,
}}
MenuProps={{
disableScrollLock: true,
}}
defaultValue={selectedAction.app_version}
onChange={(event) => {
console.log("VAL: ", event.target.value)
console.log("App: ", selectedApp)
console.log("VAL: ", event.target.value)
console.log("App: ", selectedApp)
const newversion = selectedApp.versions.find(
(tmpApp) => tmpApp.version == event.target.value
);
@@ -3051,15 +3162,6 @@ const ParsedAction = (props) => {
) : null}
</div>
</div>
<Divider
style={{
marginBottom: "10px",
marginTop: "10px",
height: "1px",
width: "100%",
backgroundColor: "rgb(91, 96, 100)",
}}
/>
<div style={{display: "flex"}}>
<div style={{flex: 5}}>
<Typography style={{color: "rgba(255,255,255,0.7)"}}>Name</Typography>
@@ -3308,10 +3410,10 @@ const ParsedAction = (props) => {
</span>
)}
{selectedApp.name !== undefined &&
selectedAction.authentication !== null &&
selectedAction.authentication !== undefined &&
selectedAction.authentication.length === 0 &&
requiresAuthentication ? (
selectedAction.authentication !== null &&
selectedAction.authentication !== undefined &&
selectedAction.authentication.length === 0 &&
requiresAuthentication ? (
<div style={{ marginTop: 15 }}>
<Tooltip
color="primary"
@@ -3466,13 +3568,13 @@ const ParsedAction = (props) => {
</div>
) : null}
{showEnvironment !== undefined && showEnvironment && environments.length > 1 ? (
{showEnvironment !== undefined && showEnvironment && environments.length > 1 && !isIntegration ? (
<div style={{ marginTop: "20px" }}>
<Typography style={{color: "rgba(255,255,255,0.7)"}}>Environment</Typography>
<Select
MenuProps={{
disableScrollLock: true,
}}
MenuProps={{
disableScrollLock: true,
}}
value={
selectedActionEnvironment === undefined || selectedActionEnvironment === null ||
selectedActionEnvironment.Name === undefined || selectedActionEnvironment.Name === null
@@ -3629,7 +3731,6 @@ const ParsedAction = (props) => {
return option.category_label !== undefined && option.category_label !== null && option.category_label.length > 0 ? "Most used" : "All Actions";
}}
renderGroup={(params) => {
//return null
return (
<li key={params.key}>
@@ -3807,7 +3908,7 @@ const ParsedAction = (props) => {
backgroundColor: theme.palette.inputColor,
borderRadius: theme.palette.borderRadius,
}}
label="Find Actions"
label={isIntegration ? "Choose a category" : "Find Actions"}
variant="outlined"
name={`disable_autocomplete_${Math.random()}`}
+130 -4
View File
@@ -38,6 +38,15 @@ import {
} from '@mui/icons-material';
import { DataGrid, GridColDef, GridValueGetterParams } from '@mui/x-data-grid'
import {
Search as SearchIcon,
} from "@mui/icons-material";
import {
InputAdornment,
} from "@mui/material"
import ClearIcon from '@mui/icons-material/Clear';
const useStyles = makeStyles({
notchedOutline: {
@@ -150,7 +159,6 @@ const RuntimeDebugger = (props) => {
const submitSearch = (workflowId, status, startTime, endTime, cursor, limit) => {
handleWorkflowUsageCount(workflows)
//setResultRows([])
setSearchLoading(true)
const fetchData = {
@@ -294,7 +302,6 @@ const RuntimeDebugger = (props) => {
toast(`Failed to force continue: ${error}`)
})
}
const imageSize = 30
const timenowUnix = Math.floor(Date.now() / 1000)
const columns: GridColDef[] = [
@@ -696,11 +703,130 @@ const RuntimeDebugger = (props) => {
});
}
const [searchQuery, setSearchQuery] = useState("");
const [filteredRows, setFilteredRows] = useState([]);
const [defaultRows, setDefaultRows] = useState([]);
const handleQueryChange = (e) => {
const query = e.target.value.toLowerCase();
setSearchQuery(query);
}
useEffect(() => {
setDefaultRows(resultRows);
}, [resultRows]);
useEffect(() => {
if (searchQuery.trim() === "") {
setFilteredRows(defaultRows);
} else {
const filterRow = defaultRows.filter((data) => {
//Filter workflow base on the workflow status
if (data.status.toLowerCase().includes(searchQuery)) {
return true;
}
//Filter workflow base on workflow name
if (data.workflow.name.toLowerCase().includes(searchQuery)) {
return true;
}
//Filter the workflow base on execution argument
if (data.execution_argument && data.execution_argument.length > 0) {
if (data.execution_argument.toLowerCase().includes(searchQuery)) {
return true;
}
}
//Filter the workflow base on the result
if (data.results && data.results.length > 0) {
for (let result of data.results) {
if (result && result.result && result.result.toLowerCase().includes(searchQuery)) {
return true;
}
}
}
return false;
});
setFilteredRows(filterRow);
}
}, [searchQuery, defaultRows]);
return (
<div style={{minWidth: 1150, maxWidth: 1150, margin: "auto", }}>
<div style={{display: "flex", }}>
<div style={{display: 'flex', flexDirection: 'column'}}>
<h1 style={{flex: 3, }}>Workflow Run Debugger {totalCount !== 0 ? ` (~${totalCount})` : ""}</h1>
<div style={{position: 'relative', right: 10, marginBottom: 10}}>
<TextField
fullWidth
value={searchQuery}
style={{
backgroundColor: theme.palette.inputColor,
marginTop: 20,
marginLeft: 10,
marginRight: 12,
width: 693,
height: 55,
borderRadius: 8,
fontSize: 16,
marginBottom: 15,
}}
InputProps={{
style: {
color: "white",
fontSize: "1em",
height: 55,
width: 693,
borderRadius: 8,
},
startAdornment: (
<InputAdornment position="start">
<SearchIcon style={{ marginLeft: 5}} />
</InputAdornment>
),
endAdornment: (
<InputAdornment position="end">
{searchQuery.length > 0 && (
<ClearIcon
style={{
color: "white",
cursor: "pointer",
marginRight: 10
}}
onClick={() => setSearchQuery('')}
/>
)}
<button
type="button"
style={{
backgroundImage:
"linear-gradient(to right, rgb(248, 106, 62), rgb(243, 64, 121))",
color: "white",
border: "none",
padding: "10px 20px",
width: 100,
height: 35,
borderRadius: 17.5,
cursor: "pointer",
}}
>
Search
</button>
</InputAdornment>
),
}}
onChange={(e)=>{handleQueryChange(e)}}
color="primary"
placeholder="Search Workflow Name, Status, Execution Argument, Results.."
id="shuffle_search_field"
/>
</div>
</div>
{selectedWorkflowExecutions.length > 0 ?
<ButtonGroup>
<Tooltip title="Reruns ALL selected workflows. This will make a new execution for them, and not continue the existing.">
@@ -952,7 +1078,7 @@ const RuntimeDebugger = (props) => {
</form>
<div style={{height: 700, padding: "10px 0px 10px 0px", }}>
<DataGrid
rows={resultRows}
rows={filteredRows}
columns={columns}
pageSize={rowsPerPage}
rowsPerPageOptions={[10, 20, 50, 100]}
+64
View File
@@ -715,6 +715,64 @@ const SearchData = props => {
</Card>
)
}
const DiscordHits = ({ hits }) => {
const [mouseHoverIndex, setMouseHoverIndex] = useState(0);
var tmp = searchOpen
if (!searchOpen) {
return null
}
const positionInfo = document.activeElement.getBoundingClientRect()
const outerlistitemStyle = {
width: "100%",
overflowX: "hidden",
overflowY: "hidden",
borderBottom: "1px solid rgba(255,255,255,0.4)",
}
if (hits.length > 4) {
hits = hits.slice(0, 4)
}
const type = "Discord Text"
const handleHitClick = (url) => {
const modifiedUrl = url.replace('https://ptb.discord.com/', 'https://discord.com/');
window.open(modifiedUrl, '_blank');
};
return (
<Card elevation={0} style={{ marginRight: 10, marginTop: 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 470, boxShadows: "none", }}>
<Typography variant="h6" style={{ margin: "10px 10px 0px 20px", color: "#FF8444", borderBottom: "1px solid", width: 152 }}>
Discord Chat
</Typography>
<List style={{ backgroundColor: theme.palette.inputColor, }}>
{hits.length === 0 ?
<ListItem style={outerlistitemStyle}>
<ListItemAvatar onClick={() => console.log(hits)}>
<Avatar>
<FolderIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={"No results found?"}
secondary={"Try refining your search."}
/>
</ListItem>:
hits.map((chat, index) => (
<ListItem onClick={() => handleHitClick(chat.url)} key={index} style={{ cursor: "pointer", borderBottom: "1px solid rgba(255,255,255,0.4)" }} onMouseOver={() => setMouseHoverIndex(index)}>
<ListItemAvatar>
<Avatar src="/discord-logo.png" />
</ListItemAvatar>
<ListItemText
primary={chat.text}
secondary={`User: ${(chat.user)}`}
/>
</ListItem>
))}
</List>
</Card>
);
};
const gettingStartData = !searchOpen ? (
<Grid
container
@@ -812,6 +870,7 @@ const SearchData = props => {
const CustomAppHits = connectHits(AppHits)
const CustomWorkflowHits = connectHits(WorkflowHits)
const CustomDocHits = connectHits(DocHits)
const CustomDiscordHits = connectHits(DiscordHits);
const modalView = (
<div>
@@ -831,6 +890,11 @@ const SearchData = props => {
<CustomDocHits />
</Index>
</Grid>
<Grid item xs="auto" style={{}}>
<Index indexName="discord_chat">
<CustomDiscordHits />
</Index>
</Grid>
</Grid>
</div>
)
+122 -122
View File
@@ -54,12 +54,14 @@ import { tags as t } from '@lezer/highlight';
import AceEditor from "react-ace";
import ace from "ace-builds";
import 'ace-builds/src-noconflict/mode-python';
//import 'ace-builds/src-noconflict/theme-twilight';
//import 'ace-builds/src-noconflict/theme-solarized_dark';
import 'ace-builds/src-noconflict/theme-gruvbox';
import "ace-builds/src-noconflict/ext-language_tools";
import ace from "ace-builds";
import "ace-builds/src-noconflict/ext-searchbox";
const liquidFilters = [
{"name": "Default", "value": `default: []`, "example": `{{ "" | default: "no input" }}`},
@@ -1033,7 +1035,7 @@ const CodeEditor = (props) => {
paddingLeft: 10,
}}
>
File Editor
File Editor ({localcodedata.length})
</DialogTitle>
</div>
</div>
@@ -1174,6 +1176,7 @@ const CodeEditor = (props) => {
</Menu>
</div>
}
<Button
id="basic-button"
aria-haspopup="true"
@@ -1443,132 +1446,129 @@ const CodeEditor = (props) => {
})}
</Menu>
</div>
}
<IconButton
style={{
marginLeft: isMobile ? "80%" : 30,
height: 50,
width: 50,
}}
onClick={() => {
}}
>
<Tooltip
color="primary"
title={"Test Liquid in the playground"}
placement="top"
>
<a
href="https://pwwang.github.io/liquidpy/playground/"
rel="norefferer"
target="_blank"
>
<ExtensionIcon style={{color: "rgba(255,255,255,0.7)"}}/>
</a>
</Tooltip>
</IconButton>
<IconButton
style={{
height: 50,
width: 50,
}}
disabled={isAiLoading}
onClick={() => {
autoFormat(localcodedata)
}}
>
<Tooltip
color="primary"
title={"Auto format data"}
placement="top"
>
{isAiLoading ?
<CircularProgress style={{height: 20, width: 20, color: "rgba(255,255,255,0.7)"}}/>
:
<AutoFixHighIcon style={{color: "rgba(255,255,255,0.7)"}}/>
}
</Tooltip>
</IconButton>
</div>
</div>
}
{/*
<div ref={editorRef}></div>
*/}
<div style={{
borderRadius: theme.palette.borderRadius,
position: "relative",
paddingTop: 0,
// minHeight: 548,
// overflow: "hidden",
}}>
{availableVariables !== undefined && availableVariables !== null && availableVariables.length > 0 &&
<AceEditor
value={localcodedata}
mode={selectedAction.name === "execute_python" ? "python" : ""}
theme="gruvbox"
height={isFileEditor ? 450 : 550}
width={isFileEditor ? 650 : "100%"}
markers={markers}
highlightActiveLine={false}
enableBasicAutocompletion={true}
completers={[customCompleter]}
style={{
wordBreak: "break-word",
marginTop: 0,
paddingBottom: 10,
overflowY: "auto",
whiteSpace: "pre-wrap",
wordWrap: "break-word",
backgroundColor: "rgba(40,40,40,1)",
}}
onLoad={(editor) => {
highlight_variables(localcodedata)
}}
onCursorChange={(cursorPosition, editor, value) => {
setCurrentCharacter(cursorPosition.column)
setCurrentLine(cursorPosition.row)
findIndex(cursorPosition.row, cursorPosition.column)
highlight_variables(localcodedata)
//console.log("VALUE CURSOR: ", value)
}}
onChange={(value, editor) => {
// setlocalcodedata(value)
// expectedOutput(value)
// highlight_variables(value,editor)
setlocalcodedata(value)
expectedOutput(value)
highlight_variables(value)
}}
setOptions={{
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
showLineNumbers: true,
tabSize: 2,
wrap: true,
useWorker: false,
enableBasicAutocompletion: [customCompleter],
}}
// options={options}
/>
}
</div>
<div
<IconButton
style={{
marginLeft: isMobile ? "80%" : 30,
height: 50,
width: 50,
}}
onClick={() => {
}}
>
</div>
<Tooltip
color="primary"
title={"Test Liquid in the playground"}
placement="top"
>
<a
href="https://pwwang.github.io/liquidpy/playground/"
rel="norefferer"
target="_blank"
>
<ExtensionIcon style={{color: "rgba(255,255,255,0.7)"}}/>
</a>
</Tooltip>
</IconButton>
<IconButton
style={{
height: 50,
width: 50,
}}
disabled={isAiLoading}
onClick={() => {
autoFormat(localcodedata)
}}
>
<Tooltip
color="primary"
title={"Auto format data"}
placement="top"
>
{isAiLoading ?
<CircularProgress style={{height: 20, width: 20, color: "rgba(255,255,255,0.7)"}}/>
:
<AutoFixHighIcon style={{color: "rgba(255,255,255,0.7)"}}/>
}
</Tooltip>
</IconButton>
</div>
</div>
}
<div style={{
borderRadius: theme.palette.borderRadius,
position: "relative",
paddingTop: 0,
// minHeight: 548,
// overflow: "hidden",
}}>
{(availableVariables !== undefined && availableVariables !== null && availableVariables.length > 0) || isFileEditor ? (
<AceEditor
value={localcodedata}
mode={selectedAction === undefined ? "" : selectedAction.name === "execute_python" ? "python" : ""}
theme="gruvbox"
height={isFileEditor ? 450 : 550}
width={isFileEditor ? 650 : "100%"}
markers={markers}
highlightActiveLine={false}
enableBasicAutocompletion={true}
completers={[customCompleter]}
style={{
wordBreak: "break-word",
marginTop: 0,
paddingBottom: 10,
overflowY: "auto",
whiteSpace: "pre-wrap",
wordWrap: "break-word",
backgroundColor: "rgba(40,40,40,1)",
}}
onLoad={(editor) => {
highlight_variables(localcodedata)
}}
onCursorChange={(cursorPosition, editor, value) => {
setCurrentCharacter(cursorPosition.column)
setCurrentLine(cursorPosition.row)
findIndex(cursorPosition.row, cursorPosition.column)
highlight_variables(localcodedata)
//console.log("VALUE CURSOR: ", value)
}}
onChange={(value, editor) => {
// setlocalcodedata(value)
// expectedOutput(value)
// highlight_variables(value,editor)
setlocalcodedata(value)
expectedOutput(value)
highlight_variables(value)
}}
setOptions={{
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
showLineNumbers: true,
tabSize: 2,
wrap: true,
useWorker: false,
enableBasicAutocompletion: [customCompleter],
}}
// options={options}
/>
): null}
</div>
<div
style={{
}}
>
</div>
</div>
{isFileEditor ? null :
<div style={{flex: 1, marginLeft: 5, borderLeft: "1px solid rgba(255,255,255,0.3)", paddingLeft: 5, }}>
+5 -5
View File
@@ -1261,15 +1261,15 @@ const UsecaseSearch = (props) => {
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Failed to activate")
}
return response.json()
})
.then((responseJson) => {
if (responseJson.success === false) {
toast("Failed to activate the app")
var msgString = "Failed to activate the app"
if (responseJson.reason !== undefined) {
msgString += ": " + responseJson.reason
}
toast(msgString)
} else {
//toast("App activated for your organization! Refresh the page to use the app.")
}
+3 -2
View File
@@ -28,10 +28,11 @@ const theme = createTheme(adaptV4Theme({
defaultBorder: "1px solid rgba(255,255,255,0.3)",
jsonTheme: "brewer",
reactJsonStyle: {
borderRadius: 5,
border: "1px solid rgba(255,255,255,0.7)",
padding: 5,
width: "100%",
borderRadius: 5,
border: "1px solid rgba(255,255,255,0.7)",
overflowX: "auto",
},
textFieldStyle: {
backgroundColor: "#383B40",
+2587 -1930
View File
File diff suppressed because it is too large Load Diff
+253 -130
View File
@@ -235,8 +235,7 @@ export const triggers = [
long_description: "Controls a pipeline to run things",
},
];
// is_valid: cloudSyncEnabled || isCloud ? true : false,
// http://apps.cytoscape.org/apps/yfileslayoutalgorithms
cytoscape.use(edgehandles);
//cytoscape.use(clipboard);
@@ -549,7 +548,69 @@ const AngularWorkflow = (defaultprops) => {
},
"open": false,
"attachedTo": "",
});
})
// New for generated stuff
const integrationApps = [{
"id": "integration",
"name": "Integration Framework",
"type": "ACTION",
"app_version": "1.0.0",
"loop_versions": ["1.0.0"],
"authentication": {
"type": "",
},
"description": "Support-use only",
"actions": [{
"name": "Cases",
"description": "Available actions for case management",
"label": "Cases",
"parameters": [{
"name": "action",
"value": "list_tickets",
"options": [
"list_tickets",
"get_ticket",
"create_ticket",
],
"required": true,
},
{
"name": "fields",
"value": "",
"required": false,
"multiline": true,
},
/*{
"name": "options",
"value": "deduplicate,enrich",
"required": false,
"multiselect": true,
"options": [
"deduplicate",
"enrich",
]
}*/
]
}]
}]
/*
{
"name": "Email",
"label": "Email",
"parameters": [{
"name": "action",
"value": "list_email",
"options": [
"list_email",
"send_mail",
],
"required": true,
}],
}]
}]
*/
// For code editor
const [codeEditorModalOpen, setCodeEditorModalOpen] = React.useState(false);
@@ -577,8 +638,6 @@ const AngularWorkflow = (defaultprops) => {
return
}
console.log("Checking to update app with useeffect.")
for (let appkey in apps) {
const curapp = apps[appkey]
if (curapp.name !== selectedApp.name) {
@@ -610,6 +669,7 @@ const AngularWorkflow = (defaultprops) => {
setSelectedApp(curapp)
}
break
}
@@ -1539,34 +1599,38 @@ const AngularWorkflow = (defaultprops) => {
curworkflowAction.position = cyelements[cyelementsKey].position();
// workaround to fix some edgecases
if (
curworkflowAction.parameters === "" ||
curworkflowAction.parameters === null
) {
curworkflowAction.parameters = [];
}
if (
curworkflowAction.parameters === "" ||
curworkflowAction.parameters === null
) {
curworkflowAction.parameters = [];
}
if (
curworkflowAction.example === undefined ||
curworkflowAction.example === "" ||
curworkflowAction.example === null
) {
if (cyelements[cyelementsKey].data().example !== undefined) {
curworkflowAction.example = cyelements[cyelementsKey].data().example;
}
}
if (
curworkflowAction.example === undefined ||
curworkflowAction.example === "" ||
curworkflowAction.example === null
) {
if (cyelements[cyelementsKey].data().example !== undefined) {
curworkflowAction.example = cyelements[cyelementsKey].data().example;
}
}
// Override just in this place
curworkflowAction.errors = [];
curworkflowAction.isValid = true;
// Cleans up OpenAPI items
var newparams = [];
for (let parametersKey in curworkflowAction.parameters) {
const thisitem = curworkflowAction.parameters[parametersKey];
if (thisitem.name.startsWith("${") && thisitem.name.endsWith("}")) {
continue;
}
// Cleans up OpenAPI items
var newparams = [];
for (let parametersKey in curworkflowAction.parameters) {
const thisitem = curworkflowAction.parameters[parametersKey];
if (thisitem.name.startsWith("${") && thisitem.name.endsWith("}")) {
continue;
}
if (thisitem.value !== undefined && thisitem.value !== null && Array.isArray(thisitem.value)) {
thisitem.value = thisitem.value.join(",")
}
newparams.push(thisitem);
}
@@ -1578,17 +1642,17 @@ const AngularWorkflow = (defaultprops) => {
useworkflow.triggers = [];
}
var curworkflowTrigger = useworkflow.triggers.find(
(a) => a.id === cyelements[cyelementsKey].data()["id"]
);
if (curworkflowTrigger === undefined) {
curworkflowTrigger = cyelements[cyelementsKey].data();
}
var curworkflowTrigger = useworkflow.triggers.find(
(a) => a.id === cyelements[cyelementsKey].data()["id"]
);
if (curworkflowTrigger === undefined) {
curworkflowTrigger = cyelements[cyelementsKey].data();
}
curworkflowTrigger.position = cyelements[cyelementsKey].position();
if (curworkflowTrigger.canConnect === false) {
continue
}
curworkflowTrigger.position = cyelements[cyelementsKey].position();
if (curworkflowTrigger.canConnect === false) {
continue
}
newTriggers.push(curworkflowTrigger);
} else if (type === "COMMENT") {
@@ -2087,6 +2151,7 @@ const AngularWorkflow = (defaultprops) => {
const pretend_apps = [{
"name": "TBD",
"id": "TBD",
"app_name": "TBD",
"app_version": "TBD",
"description": "TBD",
@@ -2113,6 +2178,7 @@ const AngularWorkflow = (defaultprops) => {
console.log("No response")
const pretend_apps = [{
"name": "TBD",
"id": "TBD",
"app_name": "TBD",
"app_version": "TBD",
"description": "TBD",
@@ -2131,42 +2197,53 @@ const AngularWorkflow = (defaultprops) => {
return
}
// Used for e.g. Liquid testing
// Used for e.g. Liquid testing
const foundTools = responseJson.find((app) => app.name === "Shuffle Tools")
if (foundTools !== undefined && foundTools !== null) {
setToolsApp(foundTools)
}
setApps(responseJson);
// Set localstorage for the apps in the "apps" key
if (responseJson !== undefined && responseJson !== null && responseJson.length > 0) {
try {
localStorage.setItem("apps", JSON.stringify(responseJson))
} catch (e) {
console.log("Failed to set apps in localstorage: ", e)
}
}
var handledPrioritizedApps = responseJson.filter((app) => internalIds.includes(app.name.toLowerCase()));
handledPrioritizedApps = [].concat(integrationApps, handledPrioritizedApps)
if (isCloud) {
setFilteredApps(responseJson.filter((app) => !internalIds.includes(app.name.toLowerCase())));
setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name.toLowerCase())));
setPrioritizedApps(handledPrioritizedApps)
} else {
var tmpFiltered = responseJson.filter((app) => !internalIds.includes(app.name.toLowerCase()))
setFilteredApps(tmpFiltered)
setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name.toLowerCase())));
setPrioritizedApps(handledPrioritizedApps)
}
setAppsLoaded(true)
// Remove all cytoscape triggers first?
if (cy !== undefined && cy !== null) {
cy.removeListener("select");
cy.removeListener("select")
}
// Re-adding cytoscape triggers
if (cy !== undefined && cy !== null) {
cy.on("select", "node", (e) => {
onNodeSelect(e, appAuthentication);
});
onNodeSelect(e, appAuthentication)
})
}
})
.catch((error) => {
console.log("App loading error: " + error.toString());
console.log("App loading error: " + error.toString())
setAppsLoaded(true)
//toast("App loading error: "+error.toString());
//toast("App loading error: "+error.toString())
});
};
@@ -2575,7 +2652,6 @@ const AngularWorkflow = (defaultprops) => {
const node = cy.getElementById(chunkJson.id)
if (node !== undefined && node !== null) {
console.log("Node already exists: ", node)
return
}
@@ -3455,9 +3531,9 @@ const AngularWorkflow = (defaultprops) => {
cy.add(decoratorNode).unselectify();
} else {
console.log("Node already exists - don't add descriptor node");
//console.log("Node already exists - don't add descriptor node");
}
}
}
}
originalLocation = {
@@ -4014,7 +4090,7 @@ const AngularWorkflow = (defaultprops) => {
)
if (curapp === undefined || curapp === null) {
console.log("Couldn't find ID - checking with name & version")
console.log("Couldn't find app with that ID - checking with name & version")
curapp = newapps.find((a) =>
a.name === curaction.app_name &&
@@ -4024,34 +4100,60 @@ const AngularWorkflow = (defaultprops) => {
)
}
if (curapp === undefined || curapp === null) {
curapp = integrationApps.find((a) =>
a.name === curaction.app_name &&
(a.app_version === curaction.app_version ||
(a.loop_versions !== null &&
a.loop_versions.includes(curaction.app_version)))
)
}
if (curaction.template === true && curaction.name !== undefined) {
//newapps.
const parsedname = curaction.name.replaceAll(" ", "_").toLowerCase()
console.log("FIND AN ACTION AMONG THE APPS THAT MATCHES NAME: ", parsedname)
curaction.matching_actions = []
for (var newAppskey in newapps) {
for (let actionsSubkey in newapps[newAppskey].actions) {
const tmpaction = newapps[newAppskey].actions[actionsSubkey]
if (tmpaction.name.replaceAll(" ", "_").toLowerCase() === parsedname) {
console.log("MATCH!: ", newapps[newAppskey])
curaction.matching_actions.push({
"app_name": newapps[newAppskey].name,
"app_version": newapps[newAppskey].app_version,
"app_id": newapps[newAppskey].id,
"action": tmpaction,
"large_image": newapps[newAppskey].large_image,
"app_index": newAppskey,
"action_index": actionsSubkey,
})
}
curaction.matching_actions = []
for (var newAppskey in newapps) {
for (let actionsSubkey in newapps[newAppskey].actions) {
const tmpaction = newapps[newAppskey].actions[actionsSubkey]
if (tmpaction.name.replaceAll(" ", "_").toLowerCase() === parsedname) {
console.log("MATCH!: ", newapps[newAppskey])
curaction.matching_actions.push({
"app_name": newapps[newAppskey].name,
"app_version": newapps[newAppskey].app_version,
"app_id": newapps[newAppskey].id,
"action": tmpaction,
"large_image": newapps[newAppskey].large_image,
"app_index": newAppskey,
"action_index": actionsSubkey,
})
}
}
}
}
if (!curapp || curapp === undefined) {
// Check local storage has it
const foundapps = localStorage.getItem("apps")
if (foundapps !== null && foundapps !== undefined) {
const parsedapps = JSON.parse(foundapps)
if (parsedapps !== null && parsedapps !== undefined && parsedapps.length > 0) {
for (let appkey in parsedapps) {
if (parsedapps[appkey].name === curaction.app_name) {
curapp = parsedapps[appkey]
break
}
}
}
if (!curapp || curapp === undefined) {
console.log("APPS - couldn't find it: ", newapps)
} else {
console.log("No apps found in local storage")
}
}
if (!curapp || curapp === undefined) {
const tmpapp = {
name: curaction.app_name,
app_name: curaction.app_name,
@@ -4361,7 +4463,7 @@ const AngularWorkflow = (defaultprops) => {
} else {
if (refresh === true) {
setHighlightedApp(appid)
//toast("App activated for your organization! Refresh the page to use the app.")
//toast("App activated for your organisation! Refresh the page to use the app.")
getApps()
}
@@ -6037,7 +6139,6 @@ const AngularWorkflow = (defaultprops) => {
currentNode.data.isDescriptor
) {
found = true;
console.log("FOUND THE NODE!");
break;
}
}
@@ -8075,6 +8176,7 @@ const AngularWorkflow = (defaultprops) => {
const AppView = (props) => {
const { allApps, prioritizedApps, filteredApps, extraApps } = props;
//extraApps,
const [visibleApps, setVisibleApps] = React.useState(
Array.prototype.concat.apply(
@@ -8090,9 +8192,9 @@ const AngularWorkflow = (defaultprops) => {
const app = props.app;
const [hover, setHover] = React.useState(false);
if (app.id === "" || app.name === "") {
return null
}
if (app.id === "" || app.name === "") {
return null
}
const maxlen = 24;
var newAppname = app.name;
@@ -8103,9 +8205,9 @@ const AngularWorkflow = (defaultprops) => {
newAppname = newAppname.replaceAll("_", " ");
if (app.large_image === undefined || app.large_image === null || app.large_image === "") {
app.large_image = theme.palette.defaultImage
}
if (app.large_image === undefined || app.large_image === null || app.large_image === "") {
app.large_image = theme.palette.defaultImage
}
const image = app.large_image !== undefined && app.large_image !== null && app.large_image !== "" ? app.large_image : theme.palette.defaultImage
@@ -8611,11 +8713,14 @@ const AngularWorkflow = (defaultprops) => {
event.target.blur(event);
}
}}
onChange={(event) => {
runSearch(event.target.value)
}}
onBlur={(event) => {
//navigate(`?q=${event.target.value}`)
runSearch(event.target.value);
//runSearch(event.target.value)
}}
/>
{visibleApps.length > extraApps.length ? (
@@ -8625,6 +8730,10 @@ const AngularWorkflow = (defaultprops) => {
return null;
}
if (app.id === "integration" && userdata.support !== true) {
return null
}
var extraMessage = ""
if (index == 2) {
extraMessage = <div style={{ marginTop: 5 }} />
@@ -8655,7 +8764,7 @@ const AngularWorkflow = (defaultprops) => {
}}
>
<Typography variant="body1" color="textSecondary">
Click one of the relevant public apps below to Activate it for your organization.
Click one of the relevant public apps below to Activate it for your organisation.
</Typography>
<InstantSearch searchClient={searchClient} indexName="appsearch" onClick={() => {
console.log("CLICKED")
@@ -8667,19 +8776,22 @@ const AngularWorkflow = (defaultprops) => {
</InstantSearch>
</div>
:
<div
style={{marginTop: 100, }}
/>}
<div style={{marginLeft: 10, marginTop: 10, marginBottom: 100, }}>
<Typography variant="body1" color="textSecondary">
Apps need to be activated before they can be used. Search from our 2500+ apps to activate them for your organisation.
</Typography>
</div>
}
</div>
) : apps.length > 0 ? (
<div
style={{ textAlign: "center", width: leftBarSize, marginTop: 10 }}
style={{ textAlign: "center", width: leftBarSize, marginTop: 10, marginLeft: 5, marginRight: 5, }}
onLoad={() => {
console.log("Should load in extra apps?")
}}
>
<Typography variant="body1" color="textSecondary">
Couldn't find the apps you were looking for? Searching unactivated apps. Click one of the below apps to Activate it for your organization.
Couldn't find the apps you were looking for? Searching unactivated apps. Click one of these apps to Activate it for your organisation.
</Typography>
<InstantSearch searchClient={searchClient} indexName="appsearch" onClick={() => {
console.log("CLICKED")
@@ -8741,12 +8853,20 @@ const AngularWorkflow = (defaultprops) => {
return
}
console.log("action input: ", e)
if (selectedApp.actions.length === 1) {
// Find if there's a new app
const newApp = apps.find((app) => (app.name === selectedApp.name && app.app_version !== selectedApp.app_version) || app.id == selectedApp.id)
if (newApp !== undefined && newApp !== null) {
const newaction = selectedApp.actions.find(
(a) => a.name === e.target.value
);
if (selectedApp.actions !== undefined && selectedApp.actions !== null && selectedApp.actions.length > 1) {
setSelectedApp(newApp)
}
selectedApp.actions = newApp.actions
}
}
const newaction = selectedApp.actions.find((a) => a.name === e.target.value)
if (newaction === undefined || newaction === null) {
toast("Failed to find the action you selected. Please try again or contact support@shuffler.io if it persists.");
return;
@@ -8833,7 +8953,6 @@ const AngularWorkflow = (defaultprops) => {
if (newSelectedAction.app_name === "Shuffle Tools") {
const iconInfo = GetIconInfo(newSelectedAction);
console.log("ICONINFO: ", iconInfo);
const svg_pin = `<svg width="${svgSize}" height="${svgSize}" viewBox="0 0 ${svgSize} ${svgSize}" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="${iconInfo.icon}" fill="${iconInfo.iconColor}"></path></svg>`;
const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin);
newSelectedAction.large_image = svgpin_Url;
@@ -8860,8 +8979,6 @@ const AngularWorkflow = (defaultprops) => {
// Further checks if those fields are already set in a previously used action
newSelectedAction = RunAutocompleter(newSelectedAction);
console.log("newaction: ", newaction)
if (
newaction.return !== undefined &&
newaction.return !== null &&
@@ -13927,6 +14044,10 @@ const AngularWorkflow = (defaultprops) => {
return null
}
if (userdata.active_org === undefined || userdata.active_org === null) {
return null
}
const isCorrectOrg = workflow.public === true || userdata.active_org.id === undefined || userdata.active_org.id === null || workflow.org_id === null || workflow.org_id === undefined || workflow.org_id.length === 0 || userdata.active_org.id === workflow.org_id
return (
@@ -13959,7 +14080,7 @@ const AngularWorkflow = (defaultprops) => {
<b>Warning</b>: Change <span
style={{color: "#f85a3e", cursor: "pointer"}}
onClick={() => {
toast("Changing to correct organization. Please wait a few seconds.")
toast("Changing to correct organisation. Please wait a few seconds.")
localStorage.setItem("globalUrl", "");
localStorage.setItem("getting_started_sidebar", "open");
@@ -13994,7 +14115,7 @@ const AngularWorkflow = (defaultprops) => {
window.location.reload();
}, 2000);
toast("Successfully changed active organization - refreshing!");
toast("Successfully changed active organisation - refreshing!");
} else {
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.length > 0) {
toast(responseJson.reason);
@@ -14316,7 +14437,7 @@ const AngularWorkflow = (defaultprops) => {
)
}
const shownErrors = !isMobile && !workflow.public && workflow.errors !== undefined && workflow.errors !== null && workflow.errors.length > 0 && showErrors ?
const shownErrors = !isMobile && workflow.errors !== undefined && workflow.errors !== null && workflow.errors.length > 0 && showErrors && (!workflow.public || userdata.support === true) ?
<div
style={{
border: "1px solid rgba(255,255,255,0.1)",
@@ -14348,8 +14469,6 @@ const AngularWorkflow = (defaultprops) => {
<Typography variant="body22">
{/*<WarningIcon style={{marginRight: 5, height: 15, width: 15, }} />*/}
<b>Workflow Issues:</b> {workflow.errors.length}
</Typography>
<Typography
@@ -14573,7 +14692,7 @@ const AngularWorkflow = (defaultprops) => {
</Tooltip>
)}
{/*userdata.avatar === creatorProfile.github_avatar ? null :*/}
<Tooltip color="primary" title={workflow.public === true ? "Use this Workflow in your organization" : "Save Workflow"} placement="top">
<Tooltip color="primary" title={workflow.public === true ? "Use this Workflow in your organisation" : "Save Workflow"} placement="top">
<span>
<Button
disabled={savingState !== 0}
@@ -14778,6 +14897,7 @@ const AngularWorkflow = (defaultprops) => {
console.log("SHOW EDIT VIEW!")
setEditWorkflowModalOpen(true)
setLastSaved(false)
}}
>
<EditIcon />
@@ -14922,6 +15042,7 @@ const AngularWorkflow = (defaultprops) => {
lastSaved={lastSaved}
aiSubmit={aiSubmit}
apps={apps}
expansionModalOpen={codeEditorModalOpen}
setExpansionModalOpen={setCodeEditorModalOpen}
setEditorData={setEditorData}
@@ -14938,8 +15059,6 @@ const AngularWorkflow = (defaultprops) => {
defaultReturn = null
} else if (selectedTrigger.trigger_type === "SUBFLOW") {
defaultReturn = <SubflowSidebar />
// } else if (selectedTrigger.trigger_type === "PIPELINE") {
// defaultReturn = <PipelineSidebar />
} else if (selectedTrigger.trigger_type === "EMAIL") {
defaultReturn = <EmailSidebar />
} else if (selectedTrigger.trigger_type === "USERINPUT") {
@@ -16498,8 +16617,7 @@ const AngularWorkflow = (defaultprops) => {
width: imgsize,
height: imgsize,
border: `2px solid ${statusColor}`,
borderRadius:
executionData.start === data.action.id ? 25 : 5,
borderRadius: executionData.start === data.action.id ? 25 : 5,
}}
/>
);
@@ -16529,8 +16647,7 @@ const AngularWorkflow = (defaultprops) => {
width: imgsize,
height: imgsize,
border: `2px solid ${statusColor}`,
borderRadius:
executionData.start === data.action.id ? 25 : 5,
borderRadius: executionData.start === data.action.id ? 25 : 5,
background: `linear-gradient(to right, ${nodedata.fillGradient})`,
};
@@ -16888,15 +17005,15 @@ const AngularWorkflow = (defaultprops) => {
style={{}}
>
<b>{data.name}</b>
{checked.valid ?
<Chip
style={{marginLeft: 10, padding: 0, cursor: "pointer",}}
label={"JSON"}
variant="outlined"
color="secondary"
/>
: null}
{showVariable ? data.value : null}
{checked.valid ?
<Chip
style={{marginLeft: 10, padding: 0, cursor: "pointer",}}
label={"JSON"}
variant="outlined"
color="secondary"
/>
: null}
{showVariable ? data.value : null}
</Typography>
</IconButton>
:
@@ -16908,25 +17025,25 @@ const AngularWorkflow = (defaultprops) => {
</Typography>
}
{open ?
checked.valid ?
<ReactJson
src={checked.result}
theme={theme.palette.jsonTheme}
style={theme.palette.reactJsonStyle}
collapsed={data.value.length < 10000 ? false : true}
displayDataTypes={false}
name={"Parsed data for variable " + data.name}
/>
:
<Typography
variant="body2"
style={{
whiteSpace: 'pre-line',
}}
color="textSecondary"
>
{data.value}
</Typography>
checked.valid ?
<ReactJson
src={checked.result}
theme={theme.palette.jsonTheme}
style={theme.palette.reactJsonStyle}
collapsed={data.value.length < 10000 ? false : true}
displayDataTypes={false}
name={"Parsed data for variable " + data.name}
/>
:
<Typography
variant="body2"
style={{
whiteSpace: 'pre-line',
}}
color="textSecondary"
>
{data.value}
</Typography>
: null}
</div>
)
@@ -17006,6 +17123,10 @@ const AngularWorkflow = (defaultprops) => {
return "You can't use localhost in apps. Use the external ip or url of the server instead"
}
if (stringjson.includes("manifest unknown")) {
return "The app's Docker Image is not available in the environment yet. Re-run the app to force a re-download of the app. If the problem persists, contact support"
}
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."
}
@@ -17241,7 +17362,7 @@ const AngularWorkflow = (defaultprops) => {
width: imgsize,
height: imgsize,
border: `2px solid ${statusColor}`,
filter: curapp === undefined ? "grayscale(100%)" : null,
filter: curapp === undefined ? "grayscale(100%)" : null,
}}
/>
)}
@@ -19079,6 +19200,8 @@ const AngularWorkflow = (defaultprops) => {
</div>
const changeActionParameterCodeMirror = (event, count, data, actionlist) => {
// Check if event.target.value is an array. If it is, split with comma
if (data.startsWith("${") && data.endsWith("}")) {
// PARAM FIX - Gonna use the ID field, even though it's a hack
const paramcheck = selectedAction.parameters.find(param => param.name === "body")
+1 -1
View File
@@ -2073,7 +2073,7 @@ const AppCreator = (defaultprops) => {
};
if (item.action_label !== undefined && item.action_label !== "" && item.action_label !== "No Label") {
console.log("Action label: ", item.action_label)
//console.log("Action label: ", item.action_label)
data.paths[item.url][item.method.toLowerCase()]["x-label"] = item.action_label
}
+14 -5
View File
@@ -82,11 +82,16 @@ const chipStyle = {
// Fixes names by making them uppercase and such
// Used for labels. A lot of places don't use this yet
export const FixName = (name) => {
if (name === undefined || name === null) {
return ""
}
const newAppname = (
name.charAt(0).toUpperCase() + name.substring(1)
).replaceAll("_", " ");
return newAppname;
};
).replaceAll("_", " ")
return newAppname
}
// Takes input of e.g. $node.data.#.asd and a matching value from a json blob
@@ -1832,7 +1837,11 @@ const Apps = (props) => {
})
.then((responseJson) => {
if (responseJson.success === false) {
toast("Failed to activate the app")
if (responseJson.reason !== undefined) {
toast("Failed to activate the app: "+responseJson.reason);
} else {
toast("Failed to activate the app");
}
} else {
//toast("App activated for your organization! Refresh the page to use the app.")
if (appExists) {
@@ -2052,7 +2061,7 @@ const Apps = (props) => {
to={`/apps/edit/${selectedApp.id}`}
style={{ textDecoration: "none", color: "inherit" }}
>
<Typography variant="h6">{selectedApp.name}</Typography>
<Typography variant="h6">{FixName(selectedApp.name)}</Typography>
</Link>
) : null}
</Breadcrumbs>
+69 -54
View File
@@ -1,33 +1,35 @@
import React, { useState, useEffect } from "react";
import theme from '../theme.jsx';
import {isMobile} from "react-device-detect";
import { isMobile } from "react-device-detect";
import AppGrid from "../components/AppGrid.jsx"
import WorkflowGrid from "../components/WorkflowGrid.jsx"
import CreatorGrid from "../components/CreatorGrid.jsx"
import DocsGrid from "../components/DocsGrid.jsx"
import DiscordChat from "../components/DiscordChat.jsx";
import { useNavigate } from "react-router-dom";
import {
Tabs,
Tab,
import {
Tabs,
Tab,
} from "@mui/material";
import {
Apps as AppsIcon,
Code as CodeIcon,
Chat as ChatIcon,
EmojiObjects as EmojiObjectsIcon,
Description as DescriptionIcon,
Description as DescriptionIcon,
} from "@mui/icons-material";
// Should be different if logged in :|
const Search = (props) => {
const { globalUrl, isLoaded, serverside, userdata, hidemargins, isHeader} = props;
const { globalUrl, isLoaded, serverside, userdata, hidemargins, isHeader } = props;
let navigate = useNavigate();
const [curTab, setCurTab] = useState(0);
const iconStyle = { marginRight: isHeader ? null : 10 };
const [curTab, setCurTab] = useState(0);
const iconStyle = { marginRight: isHeader ? null : 10 };
useEffect(() => {
if (serverside !== true && window.location.search !== undefined && window.location.search !== null) {
@@ -56,7 +58,7 @@ const Search = (props) => {
maxWidth: 1024,
scrollX: "hidden",
overflowX: "hidden",
justifyContent: isHeader ? "center" : null,
justifyContent: isHeader ? "center" : null,
}
const boxStyle = {
@@ -68,49 +70,52 @@ const Search = (props) => {
paddingRight: isHeader ? null : 30,
paddingBottom: isHeader ? null : 30,
paddingTop: hidemargins === true ? 0 : isHeader ? null : 30,
display: "flex",
display: "flex",
flexDirection: "column",
overflowX: "hidden",
minHeight: 400,
}
const views = {
0: "apps",
1: "workflows",
2: "docs",
3: "creators",
}
0: "apps",
1: "workflows",
2: "docs",
3: "creators",
4: "discord",
}
const setConfig = (event, inputValue) => {
const newValue = parseInt(inputValue)
setCurTab(newValue)
if (newValue === 0) {
document.title = "Shuffle - search - apps";
} else if (newValue === 1) {
document.title = "Shuffle - search - workflows";
} else if (newValue === 2) {
document.title = "Shuffle - search - documentation";
} else if (newValue === 3) {
document.title = "Shuffle - search - creators";
} else {
document.title = "Shuffle - search";
}
setCurTab(newValue)
if (newValue === 0) {
document.title = "Shuffle - search - apps";
} else if (newValue === 1) {
document.title = "Shuffle - search - workflows";
} else if (newValue === 2) {
document.title = "Shuffle - search - documentation";
} else if (newValue === 3) {
document.title = "Shuffle - search - creators";
} else if (newValue === 4) {
document.title = "Shuffle - search - Discord Chat";
}else {
document.title = "Shuffle - search";
}
const urlSearchParams = new URLSearchParams(window.location.search)
const params = Object.fromEntries(urlSearchParams.entries())
const foundQuery = params["q"]
var extraQ = ""
if (foundQuery !== null && foundQuery !== undefined) {
extraQ = "&q="+foundQuery
extraQ = "&q=" + foundQuery
}
if ((serverside === false || serverside === undefined) && window.location.pathname.includes("/search")) {
navigate(`/search?tab=${views[newValue]}`+extraQ)
navigate(`/search?tab=${views[newValue]}` + extraQ)
}
}
}
if (isLoaded === false) {
return null
@@ -118,18 +123,18 @@ const Search = (props) => {
// Random names for type & autoComplete. Didn't research :^)
const landingpageDataBrowser =
<div style={{paddingBottom: hidemargins === true ? 0 : 100, color: "white", }}>
const landingpageDataBrowser =
<div style={{ paddingBottom: hidemargins === true ? 0 : 100, color: "white", }}>
<div style={boxStyle}>
<Tabs
style={{width: isHeader ? 765 : 610, margin: isHeader? null :"auto", marginTop: hidemargins === true ? 0 : isHeader ? null : 25, }}
style={{ width: isHeader ? 765 : 610, margin: isHeader ? null : "auto", marginTop: hidemargins === true ? 0 : isHeader ? null : 25, }}
value={curTab}
indicatorColor="primary"
textColor="secondary"
onChange={setConfig}
aria-label="disabled tabs example"
variant="scrollable"
scrollButtons="auto"
scrollButtons="auto"
>
<Tab
label=<span>
@@ -143,36 +148,46 @@ const Search = (props) => {
/>
<Tab
label=<span>
<DescriptionIcon style={iconStyle} /> Docs
<DescriptionIcon style={iconStyle} /> Docs
</span>
/>
<Tab
label=<span>
<EmojiObjectsIcon style={iconStyle} /> Creators
<EmojiObjectsIcon style={iconStyle} /> Creators
</span>
/>
<Tab
label=<span>
<ChatIcon style={iconStyle} /> Discord Chat
</span>
/>
</Tabs>
{curTab === 0 ?
{curTab === 0 ?
<AppGrid maxRows={3} isHeader={true} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
curTab === 1 ?
window.location.pathname === "/search" ?
<WorkflowGrid maxRows={3} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
curTab === 1 ?
window.location.pathname === "/search" ?
<WorkflowGrid maxRows={3} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
<WorkflowGrid maxRows={3} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
<WorkflowGrid maxRows={3} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
curTab === 2 ?
<DocsGrid maxRows={6} parsedXs={12} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
curTab === 3 ?
<CreatorGrid parsedXs={4} isHeader={true} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
null}
curTab === 2 ?
<DocsGrid maxRows={6} parsedXs={12} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
curTab === 3 ?
<CreatorGrid parsedXs={4} isHeader={true} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
curTab === 4 ?
<DiscordChat isMobile={isMobile} />
:
null}
</div>
</div>
//{/*alternativeView={true} />*/}
const loadedCheck = isLoaded ?
const loadedCheck = isLoaded ?
<div>
<div style={bodyDivStyle}>{landingpageDataBrowser}</div>
</div>
@@ -181,7 +196,7 @@ const Search = (props) => {
</div>
// #1f2023?
return(
return (
<div style={{}}>
{loadedCheck}
</div>
+295 -41
View File
@@ -9,14 +9,16 @@ import {
Button,
Divider,
TextField,
Modal,
} from "@mui/material";
//import { useAlert
import { ToastContainer, toast } from "react-toastify"
import { ToastContainer, toast } from "react-toastify";
import "../codeeditor-index.css";
import { FileCopy, Visibility, VisibilityOff } from "@mui/icons-material";
import IconButton from "@mui/material/IconButton";
import { Tooltip } from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
const Settings = (props) => {
const { globalUrl, isLoaded, userdata, setUserData } = props;
@@ -44,14 +46,13 @@ const Settings = (props) => {
// Used for error messages etc
const [passwordFormMessage, setPasswordFormMessage] = useState("");
const [firstrequest, setFirstRequest] = useState(true);
const [userSettings, setUserSettings] = useState({});
const [showApiKey, setShowApiKey] = useState(false);
const [apiKeyCopied, setApiKeyCopied] = useState(false);
const [accountDeleteButtonClicked, setAccountDeleteButtonClicked] = useState(false);
const handleCopyApiKey = () => {
navigator.clipboard.writeText(userSettings.apikey);
setApiKeyCopied(true);
@@ -135,6 +136,241 @@ const Settings = (props) => {
return currentOwner;
};
const handleAccountDelete = () => {
setAccountDeleteButtonClicked(true);
};
const DeleteAccountPopUp = () => {
const [userDeleteAccepted, setUserDeleteAccepted] = useState(false);
const [password, setPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [disabled, setDisabled] = useState(true);
const [open, setOpen] = useState(true);
const boxStyling = {
position: "relative",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
zIndex: "9999",
backgroundColor: "#1a1a1a",
color: "white",
padding: 20,
borderRadius: 5,
boxShadow: "0 0 10px rgba(0, 0, 0, 0.3)",
width: 430,
height: 430,
};
const closeIconButtonStyling = {
color: "white",
border: "none",
backgroundColor: "transparent",
marginLeft: "90%",
width: 20,
height: 20,
cursor: "pointer",
};
const handlePasswordVisibility = () => {
setShowPassword(!showPassword);
};
const buttonStyle = {
marginTop: 20,
height: 50,
border: "none",
width: "100%",
fontSize: 16,
backgroundColor: disabled ? "gray" : "red",
color: "white",
cursor: disabled === false && "pointer",
};
const checkboxStyle = {
position: "relative",
cursor: "pointer",
display: "inline-block",
width: 20,
height: 20,
backgroundColor: "#ccc",
borderRadius: 4,
};
const checkmarkStyle = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
content: "",
width: 10,
height: 10,
backgroundColor: "#fff",
borderRadius: 2,
display: "none",
};
const handlePasswordChange = (e) => {
setPassword(e.target.value);
};
const handleCheckBoxEvent = () => {
setUserDeleteAccepted(!userDeleteAccepted);
};
useEffect(() => {
if (password.length > 8 && userDeleteAccepted) {
setDisabled(false);
} else {
setDisabled(true);
}
}, [password, userDeleteAccepted]);
function removeAllCookies() {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i];
var eqPos = cookie.indexOf("=");
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/";
}
}
const handleDeleteAccount = () => {
const baseURL = globalUrl;
const userID = userdata.id;
const url = `${baseURL}/api/v1/users/${userID}/remove`;
fetch(url, {
mode: "cors",
method: "DELETE",
body: JSON.stringify({ password }),
credentials: "include",
crossDomain: true,
withCredentials: true,
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((data) => {
if (data.success) {
toast.success(
"Your account delete successfully! redirecting in 3 sec.."
);
removeAllCookies();
window.location.pathname = "/";
} else {
toast.error(`${data.reason}`);
}
})
.catch((error) => {
console.error(
"There was a problem with your fetch operation:",
error
);
});
};
return (
<Modal open= {open} >
<div style={boxStyling}>
<button
style={closeIconButtonStyling}
onClick={() => setAccountDeleteButtonClicked(false)}
>
<CloseIcon />
</button>
<h1 style={{textAlign:"center", margin : "0 0 20px 0"}}>Account</h1>
{/* <div style={{paddingLeft: 15}} > */}
<div
style={{
display: "flex",
flexDirection: "column",
textAlign: "left",
// paddingLeft: 15
// marginLeft: 20
}}
>
<label>If you delete your account then:</label>
<ul style={{ textAlign: "left" }}>
<li>
<label>
Your Account information will be removed from our Database
permanently.
</label>
</li>
<li>
<label>This action cannot be reversed.</label>
</li>
</ul>
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
gap: 10,
}}
>
<input
checked={userDeleteAccepted}
type="checkbox"
className="ais-RefinementList-checkbox"
onClick={handleCheckBoxEvent}
/>
<label style={{ fontSize: "16px", color: "white" }}>
I have read the above information and I agree to it completely
</label>
</div>
<div
style={{
marginTop: 20,
display: "flex",
flexDirection: "column",
gap: 8,
}}
>
<label>Enter password to delete your account</label>
<TextField
style={{
backgroundColor: theme.palette.inputColor,
flex: "1",
}}
type={showPassword ? "text" : "password"}
value={password}
onChange={handlePasswordChange}
required
placeholder="Password"
id="standard-required"
autoComplete="off"
InputProps={{
endAdornment: (
<IconButton
onClick={handlePasswordVisibility}
style={{color:"white"}}
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
),
}}
/>
</div>
<button
style={buttonStyle}
disabled={disabled}
onClick={handleDeleteAccount}
>
Delete Account
</button>
</div>
</div>
</Modal>
);
};
const onPasswordChange = () => {
const data = {
username: userSettings.username,
@@ -727,7 +963,8 @@ const Settings = (props) => {
>
Submit password change
</Button>
<h3>{passwordFormMessage}</h3>
<h3>{passwordFormMessage}</h3>
{isCloud && (
<>
<Divider style={{ marginTop: "40px" }} />
@@ -820,6 +1057,22 @@ const Settings = (props) => {
</div>
</div>
<h2>Danger Area</h2>
<Button
style={{
width: "100%",
height: "60px",
marginTop: "10px",
backgroundColor: "#d52b2b",
color: "white",
}}
// variant="contained"
// color="primary"
onClick={handleAccountDelete}
>
Delete Account
</Button>
{loadedValidationWorkflows !== undefined &&
loadedValidationWorkflows !== null
? loadedValidationWorkflows.map((data, index) => {
@@ -831,6 +1084,7 @@ const Settings = (props) => {
})
: null}
</Paper>
{accountDeleteButtonClicked && <DeleteAccountPopUp/>}
</div>
);
@@ -888,47 +1142,47 @@ const Settings = (props) => {
console.log("redirect: ", redirectUri)
const client_id = "3d272b1b782b100b1e61"
const username = userdata.id;
const scopes = "read:user";
const client_id = "3d272b1b782b100b1e61"
const username = userdata.id;
const scopes = "read:user";
const url = `https://github.com/login/oauth/authorize?access_type=offline&prompt=consent&client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${scopes}&state=username%3D${username}%26type%3Dgithub`
const url = `https://github.com/login/oauth/authorize?access_type=offline&prompt=consent&client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${scopes}&state=username%3D${username}%26type%3Dgithub`
console.log("URL: ", url);
console.log("URL: ", url);
var newwin = window.open(url, "", "width=800,height=600");
var newwin = window.open(url, "", "width=800,height=600");
// Check whether we got a callback somewhere
//var id = setInterval(function () {
// fetch(
// globalUrl + "/api/v1/triggers/gmail/" + selectedTrigger.id,
// {
// method: "GET",
// headers: { "content-type": "application/json" },
// credentials: "include",
// }
// )
// .then((response) => {
// if (response.status !== 200) {
// throw new Error("No trigger info :o!");
// }
// Check whether we got a callback somewhere
//var id = setInterval(function () {
// fetch(
// globalUrl + "/api/v1/triggers/gmail/" + selectedTrigger.id,
// {
// method: "GET",
// headers: { "content-type": "application/json" },
// credentials: "include",
// }
// )
// .then((response) => {
// if (response.status !== 200) {
// throw new Error("No trigger info :o!");
// }
// return response.json();
// })
// .then((responseJson) => {
// console.log("RESPONSE: ");
// setTriggerAuthentication(responseJson);
// clearInterval(id);
// newwin.close();
// setGmailFolders();
// })
// .catch((error) => {
// console.log(error.toString());
// });
//}, 2500);
// return response.json();
// })
// .then((responseJson) => {
// console.log("RESPONSE: ");
// setTriggerAuthentication(responseJson);
// clearInterval(id);
// newwin.close();
// setGmailFolders();
// })
// .catch((error) => {
// console.log(error.toString());
// });
//}, 2500);
//saveWorkflow(workflow);
}
//saveWorkflow(workflow);
}
const loadedCheck =
isLoaded && !firstrequest ? (
+8
View File
@@ -128,6 +128,7 @@ const useStyles = makeStyles((theme) => ({
export const GetIconInfo = (action) => {
// Finds the icon based on the action. Should be verbs.
const iconList = [
{ key: "cases", values: ["cases"] },
{ key: "cache_add", values: ["set_cache"] },
{ key: "cache_get", values: ["get_cache"] },
{ key: "filter", values: ["filter"] },
@@ -222,6 +223,13 @@ export const GetIconInfo = (action) => {
const defaultColor = "#f76b1c";
const defaultGradient = ["#fad961", "#f76b1c"];
const parsedIcons = {
cases: {
icon: "M11 3C6.58 3 3 4.79 3 7C3 9.21 6.58 11 11 11C15.42 11 19 9.21 19 7C19 4.79 15.42 3 11 3ZM3 9V12C3 14.21 6.58 16 11 16C15.42 16 19 14.21 19 12V9C19 11.21 15.42 13 11 13C6.58 13 3 11.21 3 9ZM3 14V17C3 19.21 6.58 21 11 21C12.41 21 13.79 20.81 15 20.46V17.46C13.79 17.81 12.41 18 11 18C6.58 18 3 16.21 3 14ZM20 14V17H17V19H20V22H22V19H25V17H22V14",
iconColor: "white",
iconBackgroundColor: "#8acc3f",
originalIcon: "",
fillGradient: ["#8acc3f", "#459622"],
},
cache_add: {
icon: "M11 3C6.58 3 3 4.79 3 7C3 9.21 6.58 11 11 11C15.42 11 19 9.21 19 7C19 4.79 15.42 3 11 3ZM3 9V12C3 14.21 6.58 16 11 16C15.42 16 19 14.21 19 12V9C19 11.21 15.42 13 11 13C6.58 13 3 11.21 3 9ZM3 14V17C3 19.21 6.58 21 11 21C12.41 21 13.79 20.81 15 20.46V17.46C13.79 17.81 12.41 18 11 18C6.58 18 3 16.21 3 14ZM20 14V17H17V19H20V22H22V19H25V17H22V14",
iconColor: "white",