Merge branch 'Shuffle:1.4.0' into 1.4.0

This commit is contained in:
Hari Krishna
2024-02-23 02:01:56 -08:00
committed by GitHub
22 changed files with 1051 additions and 408 deletions
+31 -22
View File
@@ -5,8 +5,6 @@ import { makeStyles } from "@mui/styles";
import { useNavigate, Link } from "react-router-dom";
import countries from "../components/Countries.jsx";
import CodeEditor from "../components/ShuffleCodeEditor.jsx";
import getLocalCodeData from "../components/ShuffleCodeEditor.jsx";
import CacheView from "../components/CacheView.jsx";
import {
@@ -1867,16 +1865,24 @@ If you're interested, please let me know a time that works for you, or set up a
{selectedAuthentication.type === "oauth" || selectedAuthentication.type === "oauth2" || selectedAuthentication.type === "oauth2-app" ?
<div>
<Typography variant="body1" color="textSecondary" style={{ marginBottom: 0, marginTop: 10 }}>
Only the name of the auth can be modified for Oauth2. Please remake the authentication to change the fields like Client ID, Secret, Scopes etc.
Only the name and url can be modified for Oauth2/OpenID connect. Please remake the authentication if you want to change the other fields like Client ID, Secret, Scopes etc.
</Typography>
</div>
:
selectedAuthentication.fields.map((data, index) => {
: null }
{selectedAuthentication.fields.map((data, index) => {
var fieldname = data.key.replaceAll("_", " ")
if (fieldname.endsWith(" basic")) {
fieldname = fieldname.substring(0, fieldname.length - 6)
}
if (selectedAuthentication.type === "oauth" || selectedAuthentication.type === "oauth2" || selectedAuthentication.type === "oauth2-app") {
if (selectedAuthentication.fields[index].key !== "url") {
return null
}
}
//console.log("DATA: ", data, selectedAuthentication)
return (
<div key={index}>
@@ -3415,24 +3421,26 @@ If you're interested, please let me know a time that works for you, or set up a
// using request id or trace id
<ListItem key={index} style={{ backgroundColor: index % 2 === 0 ? "#1f2023" : "#27292d" }}>
<ListItemText
primary={new Date(data.start_time.seconds * 1000).toISOString().slice(0, 10)}
primary={new Date(data.start_time.seconds * 1000).toLocaleString('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
})}
style={{
minWidth: 150,
maxWidth: 150,
minWidth: 200,
maxWidth: 200,
}}
/>
<ListItemText
primary={data.status}
primary={data.referrer}
style={{
minWidth: 70,
maxWidth: 70,
}}
/>
<ListItemText
primary={data.method}
style={{
minWidth: 150,
maxWidth: 150,
minWidth: 300,
maxWidth: 300,
overflow: "hidden",
}}
/>
<ListItemText
@@ -3441,6 +3449,7 @@ If you're interested, please let me know a time that works for you, or set up a
minWidth: 700,
maxWidth: 700,
overflow: "hidden",
marginLeft: 10,
}}
/>
</ListItem>
@@ -4406,7 +4415,7 @@ If you're interested, please let me know a time that works for you, or set up a
/>
<ListItemText
primary="Default"
style={{ minWidth: 100, maxWidth: 100 }}
style={{ minWidth: 110, maxWidth: 110, }}
/>
<ListItemText
primary="Actions"
@@ -4550,8 +4559,8 @@ If you're interested, please let me know a time that works for you, or set up a
/>
<ListItemText
style={{
minWidth: 80,
maxWidth: 80,
minWidth: 100,
maxWidth: 100,
overflow: "hidden",
}}
primary={environment.default ? "true" : null}
@@ -4559,7 +4568,7 @@ If you're interested, please let me know a time that works for you, or set up a
{environment.default ? null : (
<Button
variant="outlined"
style={{ marginLeft: 0, marginRight: 0, }}
style={{ marginLeft: 0, marginRight: 0, maxWidth: 150, }}
onClick={() => setDefaultEnvironment(environment)}
color="primary"
>
+252 -64
View File
@@ -121,7 +121,7 @@ import * as edgehandles from "cytoscape-edgehandles";
import CytoscapeComponent from "react-cytoscapejs";
import Draggable from "react-draggable";
import cytoscapestyle from "../defaultCytoscapeStyle.jsx";
import ShuffleCodeEditor from "../components/ShuffleCodeEditor.jsx";
import ShuffleCodeEditor from "../components/ShuffleCodeEditor1.jsx";
import { validateJson, GetIconInfo } from "../views/Workflows.jsx";
import { GetParsedPaths, internalIds, } from "../views/Apps.jsx";
@@ -13366,6 +13366,67 @@ const AngularWorkflow = (defaultprops) => {
</Link>
<h2 style={{ margin: 0 }}>{workflow.name}</h2>
</Breadcrumbs>
{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 ? null :
<Typography variant="body1">
<b>Warning</b>: Change <span
style={{color: "#f85a3e", cursor: "pointer"}}
onClick={() => {
toast("Changing to correct organization. Please wait a few seconds.")
localStorage.setItem("globalUrl", "");
localStorage.setItem("getting_started_sidebar", "open");
fetch(`${globalUrl}/api/v1/orgs/${workflow.org_id}/change`, {
mode: "cors",
credentials: "include",
crossDomain: true,
method: "POST",
body: JSON.stringify({"org_id": workflow.org_id}),
withCredentials: true,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
})
.then(function (response) {
if (response.status !== 200) {
console.log("Error in response");
}
return response.json();
})
.then(function (responseJson) {
console.log("In here?")
if (responseJson.success === true) {
if (responseJson.region_url !== undefined && responseJson.region_url !== null && responseJson.region_url.length > 0) {
console.log("Region Change: ", responseJson.region_url);
localStorage.setItem("globalUrl", responseJson.region_url);
//globalUrl = responseJson.region_url
}
setTimeout(() => {
window.location.reload();
}, 2000);
toast("Successfully changed active organization - refreshing!");
} else {
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.length > 0) {
toast(responseJson.reason);
} else {
toast("Failed changing org. Try again or contact support@shuffler.io if this persists.");
}
}
})
.catch((error) => {
console.log("error changing: ", error);
//removeCookie("session_token", {path: "/"})
})
}}
>Active Organization</span> to edit this Workflow.
</Typography>
}
</div>
<div style={{display: "flex", marginLeft: 10, }}>
{parentWorkflows.slice(0,5).map((wf, index) => {
@@ -13744,9 +13805,64 @@ const AngularWorkflow = (defaultprops) => {
</div>
: null
const RightsideBar = () => {
const [hovered, setHovered] = useState(false)
useEffect(() => {
const handleKeyDown = (event) => {
if ((event.metaKey || event.ctrlKey) && event.key === '/') {
event.preventDefault(); // Prevent default browser behavior (like opening search bar)
if (!workflow.public && !executionRequestStarted) {
executeWorkflow(executionText, workflow.start, lastSaved);
}
}
if ((event.ctrlKey || event.metaKey) && event.key === "'") {
// Check if Ctrl (Windows/Linux) or Command (Mac) key is pressed along with '/'
if (!workflow.public && !executionModalOpen) {
setExecutionModalOpen(true);
getWorkflowExecution(props.match.params.key, "");
} else if (!workflow.public && executionModalOpen) {
setExecutionModalOpen(false);
}
}
if ((event.ctrlKey || event.metaKey) && event.key === "]") {
console.log("Show workflow revisions key pressed")
if (!workflow.public) {
setShowWorkflowRevisions(true)
setSelectedRevision(workflow)
//setOriginalWorkflow(workflow)
}
}
if (( event.ctrlKey || event.metaKey ) && event.key === ";") {
if (!workflow.public && executionModalOpen) {
getWorkflowExecution(props.match.params.key, "");
}
}
if (( event.ctrlKey || event.metaKey ) && event.shiftKey) {
console.log("Shift key pressed")
if (!workflow.public && executionModalOpen) {
setExecutionRunning(false);
stop()
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
const newitem = removeParam("execution_id", cursearch);
navigate(curpath + newitem)
setExecutionModalView(0);
}
}
};
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, [executeWorkflow, executionText, workflow, lastSaved, executionRequestStarted]);
return (
<div
style={{
@@ -13802,7 +13918,7 @@ const AngularWorkflow = (defaultprops) => {
</span>
</Tooltip>
) : (
<Tooltip color="primary" title="Test Execution" placement="top">
<Tooltip color="primary" title="Test Execution (Ctrl + /)" placement="top">
<span>
<Button
disabled={
@@ -14000,7 +14116,7 @@ const AngularWorkflow = (defaultprops) => {
</Tooltip>
<Tooltip
color="secondary"
title={`Show executions (${workflowExecutions.length})`}
title={`Show executions (${workflowExecutions.length}) (Ctrl + ')`}
placement="top-start"
>
<span>
@@ -14069,7 +14185,7 @@ const AngularWorkflow = (defaultprops) => {
</Tooltip>
<Tooltip
color="secondary"
title="Show Workflow Revision History (Beta)"
title="Show Workflow Revision History (Beta) (Ctrl + ])"
placement="top"
>
<span>
@@ -14080,8 +14196,8 @@ const AngularWorkflow = (defaultprops) => {
variant={"outlined"}
onClick={() => {
setShowWorkflowRevisions(true)
setSelectedRevision(workflow)
//setOriginalWorkflow(workflow)
setSelectedRevision(workflow)
//setOriginalWorkflow(workflow)
}}
>
<RestoreIcon />
@@ -14283,6 +14399,52 @@ const AngularWorkflow = (defaultprops) => {
//return null;
};
const unPublishWorkflow = (data) => {
if (!isCloud) {
toast("Function only supported on cloud")
return
}
if (data.public !== true) {
toast("Workflow is not public. Can't unpublish");
return
}
// This ALWAYS talks to Shuffle cloud
data = JSON.parse(JSON.stringify(data));
const url = `${globalUrl}/api/v1/workflows/${data.id}/unpublish`;
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(data),
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for workflow publish :O!");
}
return response.json();
})
.then((responseJson) => {
if (responseJson.reason !== undefined) {
toast("Unpublishing: "+responseJson.reason)
}
if (responseJson.success === true) {
workflow.public = false
setWorkflow(workflow)
}
})
.catch((error) => {
toast("Failed publishing: is the workflow valid? Remember to save the workflow first.")
console.log(error.toString())
})
}
// This can execute a workflow with firestore. Used for test, as datastore is old and stuff
// Too much work to move everything over alone, so won't touch it for now
//<Button style={{borderRadius: "0px"}} color="primary" variant="contained" onClick={() => {
@@ -14538,8 +14700,8 @@ const AngularWorkflow = (defaultprops) => {
</Button>
<Button
color="secondary"
disabled
variant="outlined"
disabled={workflow.public !== true}
fullWidth
style={{ marginTop: 15, }}
onClick={() => {
@@ -14547,6 +14709,8 @@ const AngularWorkflow = (defaultprops) => {
// workflow.public = false
// setWorkflow(workflow)
// setUpdate(Math.random());
toast("Unpublishing this workflow from the search engine. It will remain public until it is deleted, as it is a copy of the original workflow.")
unPublishWorkflow(workflow)
}}
>
Unpublish Workflow
@@ -15112,6 +15276,7 @@ const AngularWorkflow = (defaultprops) => {
</a>
</Tooltip>
</div>
<Tooltip title="Refresh runs (Ctrl + ;)" arrow>
<Button
style={{ borderRadius: "0px" }}
variant="outlined"
@@ -15124,6 +15289,7 @@ const AngularWorkflow = (defaultprops) => {
<CachedIcon style={{ marginRight: 10 }} />
Refresh Runs
</Button>
</Tooltip>
<Divider
style={{
backgroundColor: "rgba(255,255,255,0.5)",
@@ -15351,48 +15517,51 @@ const AngularWorkflow = (defaultprops) => {
</div>
) : (
<div style={{ padding: isMobile ? "0px 10px 25px 10px" : "25px 15px 25px 15px", maxWidth: isMobile ? "100%" : 400, overflowX: "hidden" }}>
<Breadcrumbs
aria-label="breadcrumb"
separator=""
style={{ color: "white", fontSize: 16 }}
>
<span
style={{ color: "rgba(255,255,255,0.5)", display: "flex" }}
onClick={() => {
setExecutionRunning(false);
stop();
getWorkflowExecution(props.match.params.key, "");
setExecutionModalView(0);
setLastExecution(executionData.execution_id);
}}
<Breadcrumbs
aria-label="breadcrumb"
separator=""
style={{ color: "white", fontSize: 16 }}
>
<IconButton
style={{
paddingLeft: 0,
marginTop: "auto",
marginBottom: "auto",
}}
onClick={() => {
setExecutionRunning(false);
stop()
}}
>
<ArrowBackIcon style={{ color: "rgba(255,255,255,0.5)" }} />
</IconButton>
<h2
style={{ color: "rgba(255,255,255,0.5)", cursor: "pointer" }}
onClick={() => {
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
const newitem = removeParam("execution_id", cursearch);
navigate(curpath + newitem)
setExecutionRunning(false);
stop()
}}
>
See more runs
</h2>
</span>
</Breadcrumbs>
<span
style={{ color: "rgba(255,255,255,0.5)", display: "flex" }}
onClick={() => {
setExecutionRunning(false);
stop();
getWorkflowExecution(props.match.params.key, "");
setExecutionModalView(0);
setLastExecution(executionData.execution_id);
}}
>
<IconButton
style={{
paddingLeft: 0,
marginTop: "auto",
marginBottom: "auto",
}}
onClick={() => {
setExecutionRunning(false);
stop()
}}
>
<ArrowBackIcon style={{ color: "rgba(255,255,255,0.5)" }} />
</IconButton>
<Tooltip title="See more runs (Ctrl + Shift)" arrow>
<h2
style={{ color: "rgba(255,255,255,0.5)", cursor: "pointer" }}
onClick={() => {
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
const newitem = removeParam("execution_id", cursearch);
navigate(curpath + newitem)
setExecutionRunning(false);
stop()
}}
>
See more runs
</h2>
</Tooltip>
</span>
</Breadcrumbs>
<Divider
style={{
backgroundColor: "rgba(255,255,255,0.6)",
@@ -15456,15 +15625,19 @@ const AngularWorkflow = (defaultprops) => {
color="primary"
title="Explore logs for the workflow"
placement="top"
style={{ zIndex: 50000 }}
style={{ zIndex: 50000, }}
>
<span style={{}}>
<Button
color="primary"
style={{ float: "right", marginTop: 20, marginLeft: 10 }}
disabled={!userdata.support}
disabled={userdata.region_url !== "https://shuffler.io"}
onClick={() => {
window.open(`/api/v1/workflows/search/${executionData.execution_id}`, "_blank")
toast("Opening logs in a new tab")
setTimeout(() => {
window.open(`/api/v1/workflows/search/${executionData.execution_id}`, "_blank")
}, 250)
}}
>
<InsightsIcon color="secondary" />
@@ -17855,42 +18028,45 @@ const AngularWorkflow = (defaultprops) => {
return null
}
var newrevision = JSON.parse(JSON.stringify(revision))
// Make unix timestamp into ISO timestamp in the format July 27th, 3:05 AM
// Format: July 27th, 3:05 AM
console.log("Edited time: ", revision.edited)
//console.log("Edited time: ", revision.edited)
// Convert 1692128391 to valid timestamp
const validTimestamp = revision.edited.toString().length === 10 ? revision.edited * 1000 : revision.edited
const validTimestamp = newrevision.edited.toString().length === 10 ? newrevision.edited * 1000 : newrevision.edited
const translatedDate = new Date(validTimestamp).toLocaleString('en-US', { month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: true })
var workflowStatus = revision.status !== undefined && revision.status !== null && revision.status !== "" ? revision.status : "test"
if (revision.name !== undefined && revision.name !== null && revision.name !== "") {
if (revision.name.toLowerCase().includes("test")) {
var workflowStatus = newrevision.status !== undefined && newrevision.status !== null && newrevision.status !== "" ? newrevision.status : "test"
if (newrevision.name !== undefined && newrevision.name !== null && newrevision.name !== "") {
if (newrevision.name.toLowerCase().includes("test")) {
workflowStatus = "test"
}
if (revision.name.toLowerCase().includes("dev") || revision.name.toLowerCase().includes("staging") || revision.name.toLowerCase().includes("rollback")) {
if (newrevision.name.toLowerCase().includes("dev") || newrevision.name.toLowerCase().includes("staging") || newrevision.name.toLowerCase().includes("rollback")) {
workflowStatus = "dev"
}
if (revision.name.toLowerCase().includes("prod") || revision.name.toLowerCase().includes("main")) {
if (newrevision.name.toLowerCase().includes("prod") || newrevision.name.toLowerCase().includes("main")) {
workflowStatus = "prod"
}
}
return (
<Paper
style={{padding: "15px 15px 15px 25px", minHeight: 105, maxHeight: 105, cursor: "pointer", backgroundColor: revision.edited === selectedRevision.edited ? "rgba(255,255,255,0.3)" : theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.3)", marginBottom: 10,
style={{padding: "15px 15px 15px 25px", minHeight: 105, maxHeight: 105, cursor: "pointer", backgroundColor: newrevision.edited === selectedRevision.edited ? "rgba(255,255,255,0.3)" : theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.3)", marginBottom: 10,
}} onClick={(e) => {
if (revision.edited === selectedRevision.edited) {
if (newrevision.edited === selectedRevision.edited) {
console.log("Same revision! No setting.")
return
}
// Should render if it's not the same as workflow.edited
console.log("Clicked revision: ", revision)
console.log("Clicked revision: ", newrevision)
setLastSaved(false)
setSelectedRevision(revision)
setWorkflow(revision)
setSelectedRevision(newrevision)
setWorkflow(newrevision)
setSelectedAction({});
setSelectedApp({})
@@ -17910,7 +18086,7 @@ const AngularWorkflow = (defaultprops) => {
cy.removeListener("cxttap");
}
setupGraph(revision)
setupGraph(newrevision)
// Re-adding cytoscape triggers
if (cy !== undefined && cy !== null) {
@@ -17936,8 +18112,20 @@ const AngularWorkflow = (defaultprops) => {
cy.on("free", "node", (e) => onNodeDragStop(e, selectedAction));
cy.on("cxttap", "node", (e) => onCtxTap(e));
if (selectedAction.id !== undefined && selectedAction.id !== null && selectedAction.id !== "") {
setTimeout(() => {
const foundaction = cy.$id(selectedAction.id)
if (foundaction !== undefined && foundaction !== null) {
foundaction.select()
}
}, 250)
}
}
// Need to run through graph setup with this one
}}>
<div style={{display: "flex", }}>
+23 -19
View File
@@ -1,16 +1,11 @@
import React, { useState, useEffect } from "react";
import { useInterval } from "react-powerhooks";
import AppFramework from "../components/AppFramework.jsx";
import { makeStyles, } from "@mui/styles";
// nodejs library that concatenates classes
import classNames from "classnames";
import theme from '../theme.jsx';
import { useNavigate, Link, useParams } from "react-router-dom";
import WorkflowTemplatePopup from "../components/WorkflowTemplatePopup.jsx";
// react plugin used to create charts
//import { Line, Bar } from "react-chartjs-2";
//import { useAlert
import React, { useState, useEffect } from "react"
import { useInterval } from "react-powerhooks"
import AppFramework from "../components/AppFramework.jsx"
import { makeStyles, } from "@mui/styles"
import classNames from "classnames"
import theme from '../theme.jsx'
import { useNavigate, Link, useParams } from "react-router-dom"
import WorkflowTemplatePopup from "../components/WorkflowTemplatePopup.jsx"
import { ToastContainer, toast } from "react-toastify"
import { parsedDatatypeImages } from "../components/AppFramework.jsx"
import { findSpecificApp } from "../components/AppFramework.jsx"
@@ -96,7 +91,8 @@ const useStyles = makeStyles({
const UsecaseListComponent = (props) => {
const { keys, userdata, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows, } = props
const { keys, userdata, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows, getFramework, setFrameworkData, } = props
const [expandedIndex, setExpandedIndex] = useState(-1);
const [expandedItem, setExpandedItem] = useState(-1);
@@ -114,11 +110,13 @@ const UsecaseListComponent = (props) => {
const [firstLoad, setFirstLoad] = useState(true)
const [apps, setApps] = useState([])
const classes = useStyles();
let navigate = useNavigate();
const [mitreTags, setMitreTags] = useState([]);
const parseUsecase = (subcase) => {
const srcdata = findSpecificApp(frameworkData, subcase.type)
const dstdata = findSpecificApp(frameworkData, subcase.last)
@@ -137,13 +135,11 @@ const UsecaseListComponent = (props) => {
}
useEffect(() => {
console.log("In frameworkData useEffect: frameworkData: ", frameworkData)
//console.log("Frameworkdata changed. Use to set inputUsecase: ", frameworkData, prevSubcase)
if (frameworkData === undefined || prevSubcase === undefined) {
return
}
console.log("PAST!")
var parsedUsecase = inputUsecase
const subcase = parseUsecase(prevSubcase)
@@ -917,6 +913,9 @@ const UsecaseListComponent = (props) => {
description={inputUsecase.description}
apps={apps}
getAppFramework={getFramework}
//appSetupDone={appSetupDone}
//setAppSetupDone={setAppSetupDone}
/>
: null}
</span>
@@ -990,13 +989,15 @@ const UsecaseListComponent = (props) => {
}}>
<AppFramework
inputUsecase={inputUsecase}
frameworkData={frameworkData}
selectedOption={"Draw"}
showOptions={false}
isLoaded={true}
isLoggedIn={true}
globalUrl={globalUrl}
size={0.6}
frameworkData={frameworkData}
setFrameworkData={setFrameworkData}
/>
</div>
</div>
@@ -1713,12 +1714,15 @@ const Dashboard = (props) => {
<UsecaseListComponent
userdata={userdata}
isLoggedIn={isLoggedIn}
frameworkData={frameworkData}
keys={selectedUsecases}
isCloud={isCloud}
globalUrl={globalUrl}
workflows={workflows}
setWorkflows={setWorkflows}
frameworkData={frameworkData}
setFrameworkData={setFrameworkData}
getFramework={getFramework}
/>
{treeKeys.length > 0 ?
+61 -4
View File
@@ -13,6 +13,11 @@ import {
//import { useAlert
import { ToastContainer, toast } from "react-toastify"
import { FileCopy, Visibility, VisibilityOff } from "@mui/icons-material";
import IconButton from "@mui/material/IconButton";
import { Tooltip } from "@mui/material";
const Settings = (props) => {
const { globalUrl, isLoaded, userdata, setUserData } = props;
//const alert = useAlert();
@@ -44,6 +49,17 @@ const Settings = (props) => {
const [userSettings, setUserSettings] = useState({});
const [showApiKey, setShowApiKey] = useState(false);
const [apiKeyCopied, setApiKeyCopied] = useState(false);
const handleCopyApiKey = () => {
navigator.clipboard.writeText(userSettings.apikey);
setApiKeyCopied(true);
setTimeout(() => {
setApiKeyCopied(false);
}, 2000);
}
/*
const [userdata.eth_info, setEthInfo] = useState(userdata.eth_info !== undefined && userdata.eth_info.account !== undefined && userdata.eth_info.account.length > 0 ? userdata.eth_info : {
"account": "",
@@ -467,7 +483,7 @@ const Settings = (props) => {
>
What is the API key used for?
</a>
<TextField
{/* <TextField
style={{ backgroundColor: theme.palette.inputColor, flex: "1" }}
InputProps={{
style: {
@@ -484,7 +500,43 @@ const Settings = (props) => {
id="standard-required"
margin="normal"
variant="outlined"
/>
/> */}
<TextField
style={{ backgroundColor: theme.palette.inputColor, flex: "1" }}
InputProps={{
style: {
height: "50px",
color: "white",
},
endAdornment: (
<>
<Tooltip title={showApiKey ? "Hide API Key" : "Show API Key"}>
<IconButton
onClick={() => setShowApiKey(!showApiKey)}
>
{showApiKey ? <VisibilityOff /> : <Visibility />}
</IconButton>
</Tooltip>
<Tooltip title={apiKeyCopied ? "API Key copied!" : "Copy API Key"}>
<IconButton
onClick={handleCopyApiKey}
>
<FileCopy />
</IconButton>
</Tooltip>
</>
),
}}
color="primary"
value={showApiKey ? userSettings.apikey : '*'.repeat(36)} // Show API key if showApiKey is true, else show asterisks
required
disabled
fullWidth
placeholder="APIKEY"
id="standard-required"
margin="normal"
variant="outlined"
/>
<Button
style={{ width: "100%", height: "40px", marginTop: "10px" }}
variant="outlined"
@@ -676,8 +728,13 @@ const Settings = (props) => {
Submit password change
</Button>
<h3>{passwordFormMessage}</h3>
<Divider style={{ marginTop: "40px" }} />
<h2>Creator Incentive Program</h2>
{isCloud && (
<>
<Divider style={{ marginTop: "40px" }} />
<h2>Creator Incentive Program</h2>
</>
)}
<div style={{ display: runFlex ? "flex" : "", width: "100%" }}>
<div>
{isCloud ?
+5 -7
View File
@@ -551,9 +551,7 @@ const Workflows = (props) => {
const [field1, setField1] = React.useState("");
const [field2, setField2] = React.useState("");
const [downloadUrl, setDownloadUrl] = React.useState(
"https://github.com/frikky/shuffle-workflows"
);
const [downloadUrl, setDownloadUrl] = React.useState("https://github.com/shuffle/workflows")
const [downloadBranch, setDownloadBranch] = React.useState("master");
const [loadWorkflowsModalOpen, setLoadWorkflowsModalOpen] =
React.useState(false);
@@ -924,7 +922,7 @@ const Workflows = (props) => {
>
<DialogTitle>
<div style={{ textAlign: "center", color: "rgba(255,255,255,0.9)" }}>
Are you sure you want to delete {selectedWorkflowId.length > 0 ? filteredWorkflows.find((w) => w.id === selectedWorkflowId).name : `${selectedWorkflowIndexes.length} workflow${selectedWorkflowIndexes.length === 1 ? '' : 's'}`}? <div />
Are you sure you want to delete {selectedWorkflowId.length > 0 ? filteredWorkflows.find((w) => w.id === selectedWorkflowId)?.name : `${selectedWorkflowIndexes.length} workflow${selectedWorkflowIndexes.length === 1 ? '' : 's'}`}? <div />
Other workflows relying on {selectedWorkflowIndexes.length > 0 ? "them" : "it"} one will stop working
</div>
@@ -3630,7 +3628,7 @@ const Workflows = (props) => {
const handleGithubValidation = () => {
importWorkflowsFromUrl(downloadUrl);
setLoadWorkflowsModalOpen(false);
};
}
const workflowDownloadModalOpen = loadWorkflowsModalOpen ? (
<Dialog
@@ -3677,11 +3675,11 @@ const Workflows = (props) => {
},
}}
onChange={(e) => setDownloadUrl(e.target.value)}
placeholder="https://github.com/frikky/shuffle-apps"
placeholder="https://github.com/shuffle/workflows"
fullWidth
/>
<span style={{ marginTop: 10 }}>
Branch (default value is "master"):
Branch (default value is "main"):
</span>
<div style={{ display: "flex" }}>
<TextField