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
+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",