This commit is contained in:
Frikky
2024-12-20 21:56:33 +02:00
parent 75fdbb4ffc
commit 376a6d5173
18 changed files with 1867 additions and 926 deletions
+42 -22
View File
@@ -57,7 +57,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
: hover
? ""
: "1px solid rgba(255,255,255,0.3)",
borderImage: makeFancy ? "linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) 1" : "none",
borderImage: makeFancy ? "linear-gradient(to right, #ff8544 0%, #ec517c 50%, #9c5af2 100%) 1" : "none",
transition: 'all 0.2s ease-in-out',
}
@@ -340,7 +340,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
const circularLoader = validation ? <CircularProgress color="primary" /> : null
const errorText = openApiError?.length > 0 ? <div style={{ marginTop: 10 }}>Error: {openApiError}</div> : null
const errorText = openApiError?.length > 0 ? <div style={{ marginTop: 15, color: '#fd4c62' }}>Error: {openApiError}</div> : null
// Common dialog styles
const dialogStyle = {
@@ -400,7 +400,13 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
Create New App
</Typography>
<IconButton
onClick={onClose}
onClick={() => {
setOpenApi("")
setOpenApiError("")
setAppValidation("")
setValidation(false)
onClose()
}}
sx={{
color: 'rgba(255, 255, 255, 0.7)',
'&:hover': { bgcolor: 'rgba(255, 255, 255, 0.1)' }
@@ -477,7 +483,14 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
Create New App from Open API or Swagger
</Typography>
<IconButton
onClick={() => setOpenApiModal(false)}
onClick={() => {
setOpenApiModal(false)
setGenerateAppModal(false)
setOpenApi("")
setOpenApiError("")
setAppValidation("")
setValidation(false)
}}
sx={{
color: 'rgba(255,255,255,0.7)',
'&:hover': { bgcolor: 'rgba(255,255,255,0.1)' }
@@ -487,14 +500,16 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
</IconButton>
</DialogTitle>
<DialogContent sx={{ px: 4, py: 3 }}>
<div style={{ display: "flex", fontSize: '14px', gap: '5px', alignItems: 'center', marginBottom: '10px', fontFamily: theme?.typography?.fontFamily }}>
<Typography sx={{ color: 'rgba(255,255,255,0.85)', fontSize: '14px' }}>
<div style={{ display: "flex", fontSize: '14px', gap: '5px', alignItems: 'center', marginBottom: '10px', fontFamily: theme?.typography?.fontFamily, marginTop: '15px' }}>
<Typography sx={{ color: 'rgba(255,255,255,0.85)', fontSize: '16px' }}>
Paste in the URI for the OpenAPI or find out
</Typography>
<Link style={{
color: '#ff8544',
textDecoration: 'none',
textDecoration: 'underline',
fontSize: '16px',
fontFamily: theme?.typography?.fontFamily
}}>
How to find URI for openAPI?
</Link>
@@ -506,12 +521,13 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
fullWidth
variant="outlined"
placeholder="Open API URI"
style={{ fontFamily: theme?.typography?.fontFamily, fontSize: '16px' }}
sx={{
'& .MuiOutlinedInput-root': {
height: '40px'
height: '40px',
},
'& .MuiOutlinedInput-input::placeholder': {
fontSize: '14px'
fontSize: '16px'
}
}}
onChange={(e) => setOpenApi(e.target.value)}
@@ -526,7 +542,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
px: 3,
textTransform: 'none',
height: '40px',
fontSize: '14px',
fontSize: '16px',
fontFamily: theme?.typography?.fontFamily,
cursor: 'pointer'
}}
@@ -562,7 +578,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
sx={{
color: '#FF8544',
borderColor: '#FF8544',
px: 3,
px: 5,
py: 1,
'&:hover': {
borderColor: '#FF8544',
@@ -570,7 +586,8 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
},
textTransform: 'none',
fontSize: '14px',
fontFamily: theme?.typography?.fontFamily
fontFamily: theme?.typography?.fontFamily,
height: '40px'
}}
>
Upload
@@ -605,7 +622,8 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
},
textTransform: 'none',
py: 1.5,
fontSize: '14px',
mb: 1.5,
fontSize: '16px',
fontWeight: 500,
width: '100%',
maxWidth: '300px',
@@ -648,7 +666,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
<Typography variant="h6" sx={{
color: '#F1F1F1',
fontWeight: 500,
fontFamily: theme?.typography?.fontFamily
fontFamily: theme?.typography?.fontFamily,
}}>
Generate an app based on documentation (beta)
</Typography>
@@ -656,6 +674,10 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
onClick={() => {
setGenerateAppModal(false)
setOpenApiModal(false)
setOpenApi("")
setOpenApiError("")
setAppValidation("")
setValidation(false)
}}
sx={{
color: 'rgba(255,255,255,0.7)',
@@ -668,9 +690,9 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
<DialogContent sx={{ px: 4, py: 3, pt: 0 }}>
<Typography sx={{
color: 'rgba(255,255,255,0.85)',
mb: 3,
mb: 2,
fontSize: '14px',
mt:4,
mt: 2,
fontFamily: theme?.typography?.fontFamily
}}>
Paste in a URL, and we will make it into an app for you.
@@ -689,18 +711,15 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
color: 'white',
'& fieldset': {
borderWidth: '1px',
borderImage: 'linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) 1',
borderImageSlice: 1,
borderImage: "linear-gradient(to right, #ff8544 0%, #ec517c 50%, #9c5af2 100%) 1",
},
'&:hover fieldset': {
borderWidth: '1px',
borderImage: 'linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) 1',
borderImageSlice: 1,
borderImage: "linear-gradient(to right, #ff8544 0%, #ec517c 50%, #9c5af2 100%) 1",
},
'&.Mui-focused fieldset': {
borderWidth: '2px',
borderImage: 'linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) 1',
borderImageSlice: 1,
borderImage: "linear-gradient(to right, #ff8544 0%, #ec517c 50%, #9c5af2 100%) 1",
}
},
'& .MuiOutlinedInput-input::placeholder': {
@@ -727,6 +746,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
</DialogContent>
<DialogActions sx={{
py: 2,
pt: 1,
px: 3,
gap: 2,
display: 'flex',
@@ -736,7 +756,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
{circularLoader}
{
!validation &&
<Typography sx={{ color: 'rgba(255,255,255,0.85)', fontSize: '14px', fontFamily: theme?.typography?.fontFamily, pt: 2 }}>
<Typography sx={{ color: '#c5c5c5', fontSize: '14px', fontFamily: theme?.typography?.fontFamily, }}>
This may take multiple minutes based on the size of the documentation.
</Typography>
}
+20 -23
View File
@@ -22,8 +22,8 @@ import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import LaunchIcon from '@mui/icons-material/Launch';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import { CloudDownloadOutlined } from '@mui/icons-material';
import { findSpecificApp } from './AppFramework';
import theme from "../theme";
import { findSpecificApp } from '../components/AppFramework.jsx';
import theme from "../theme.jsx";
import YAML from 'yaml';
import { toast } from 'react-toastify';
import { Link } from 'react-router-dom';
@@ -433,7 +433,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
fontFamily: theme?.typography?.fontFamily
}}
>
<Typography component="div" sx={{ fontWeight: 500, color: "#F1F1F1", fontSize: "22px" }}>
<Typography component="div" sx={{ fontWeight: 500, color: "#F1F1F1", fontSize: "20px" }}>
About {app?.name.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase())}
</Typography>
<IconButton
@@ -464,31 +464,28 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.2)"
}}
/>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "center", paddingLeft: 8 }}>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "center", paddingLeft: 8, }}>
<div style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
}}>
<Typography variant="h5" component="div" sx={{ fontWeight: 600 }}>
{newAppname}
</Typography>
{
isCloud && (
<Link
to={"/apps/" + (app?.id || app?.objectID)}
style={{ textDecoration: "none", color: "#f85a3e", marginTop: "-2px" }}
>
<IconButton
style={{
color: "#f85a3e",
fontSize: 20,
}}
>
<OpenInNewIcon />
</IconButton>
</Link>
)
}
<Link
to={"/apps/" + (app?.id || app?.objectID)}
style={{ textDecoration: "none", color: "#f85a3e", marginTop: "-2px" }}
>
<IconButton
style={{
color: "#f85a3e",
fontSize: 16,
}}
>
<OpenInNewIcon />
</IconButton>
</Link>
</div>
<Typography
variant="body2"
@@ -547,7 +544,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
if (canEditApp) {
const editUrl = "/apps/edit/" + (app?.id || app?.objectID);
navigate(editUrl)
}else{
} else {
const forkUrl = "/apps/new?id=" + (app?.id || app?.objectID);
navigate(forkUrl)
}
@@ -735,7 +732,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
bgcolor: '#FF8544',
'&:hover': { bgcolor: '#FF8544' },
textTransform: 'none',
borderRadius: 1,
borderRadius: "4px",
py: 1,
px: 7,
fontSize: "14px",
+6 -4
View File
@@ -466,14 +466,16 @@ const AppSelection = props => {
fontSize: 16,
color: "rgba(158, 158, 158, 1)",
fontFamily: theme?.typography?.fontFamily,
lineHeight: "24px"
}}
>
Your organization has no apps yet, select your starting apps here
or discover more apps using the <span
{`${window.location.pathname.includes("my_apps") || window.location.search.includes("my_apps") ? "You have no apps yet, select your starting apps here" : "Your organization has no apps yet, select your starting apps here"}
or discover more apps using the`}
<span
onClick={() => {
navigate("/apps2?tab=all_apps")
navigate("/apps?tab=all_apps")
}}
style={{ color: "#FF8444", fontWeight: "medium", fontSize: 16, cursor:"pointer" }}>App Library</span>
style={{ color: "#FF8444", fontWeight: "medium", fontSize: 16, cursor:"pointer", marginLeft: 6 }}>App Library</span>
</span>
</div>
)
+250 -126
View File
@@ -51,11 +51,13 @@ import BillingStats from "./BillingStats.jsx";
import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
import DeleteIcon from '@mui/icons-material/Delete';
import { Context } from "../context/ContextApi.jsx";
import LicencePopup from "./LicencePopup.jsx";
const Billing = memo((props) => {
const { globalUrl, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, clickedFromOrgTab } = props;
const { globalUrl, userdata, serverside, billingInfo, stripeKey,isLoaded, selectedOrganization, handleGetOrg, clickedFromOrgTab, removeCookie} = props;
//const alert = useAlert();
let navigate = useNavigate();
const [isLoggedIn, setIsLoggedIn] = useState(false)
const [selectedDealModalOpen, setSelectedDealModalOpen] = React.useState(false);
const [dealList, setDealList] = React.useState([]);
const [dealName, setDealName] = React.useState("");
@@ -73,14 +75,17 @@ const Billing = memo((props) => {
const [currentAppRunsInNumber, setCurrentAppRunsInNumber] = useState(0);
const [alertThresholds, setAlertThresholds] = useState(selectedOrganization.Billing !== undefined && selectedOrganization.Billing.AlertThreshold !== undefined && selectedOrganization.Billing.AlertThreshold !== null ? selectedOrganization.Billing.AlertThreshold : [{ percentage: '', count: '', Email_send: false }]);
const [currentIndex, setCurrentIndex] = useState(0);
const [deleteAlertIndex, setDeleteAlertIndex] = useState(-1);
const [deleteAlertVerification, setDeleteAlertVerification] = useState(false);
useEffect(() => {
if (userdata.app_execution_limit !== undefined && userdata.app_execution_usage !== undefined) {
const percentage = (userdata.app_execution_usage / userdata.app_execution_limit) * 100;
setCurrentAppRunsInPercentage(Math.round(percentage));
setCurrentAppRunsInNumber(userdata.app_execution_limit - userdata.app_execution_usage);
}
if (userdata?.id?.length > 0 && isLoggedIn === false){
setIsLoggedIn(true)
}
}, [userdata]);
const [BillingEmail, setBillingEmail] = useState(selectedOrganization?.Billing?.Email);
@@ -182,7 +187,8 @@ const Billing = memo((props) => {
const isCloud =
window.location.host === "localhost:3002" ||
window.location.host === "shuffler.io";
window.location.host === "shuffler.io" ||
window.location.host === "sandbox.shuffler.io";
billingInfo.subscription = {
"active": true,
@@ -419,8 +425,16 @@ const Billing = memo((props) => {
const data = {
org_id: orgId,
email: newBillingEmail,
name: selectedOrganization.name,
description: selectedOrganization.description,
image: selectedOrganization.image,
defaults: selectedOrganization.defaults,
sso_config: selectedOrganization.sso_config,
mfa_required: selectedOrganization.mfa_required,
billing: {
email: newBillingEmail,
AlertThreshold: selectedOrganization?.Billing?.AlertThreshold,
Consultation: selectedOrganization?.Billing?.Consultation,
},
};
@@ -747,13 +761,21 @@ const Billing = memo((props) => {
open={openChangeEmailBox}
onClose={handleCloseChangeEmailBox}
PaperProps={{
style: {
padding: '20px',
borderRadius: '8px',
maxWidth: '500px',
width: '100%'
sx: {
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
border: theme?.palette?.DialogStyle?.border,
minWidth: '440px',
fontFamily: theme?.typography?.fontFamily,
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
zIndex: 1000,
'& .MuiDialogContent-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
'& .MuiDialogTitle-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
}
}}
}}
>
<DialogTitle style={{ fontSize: '1.5rem', fontWeight: 'bold' }}>Change Billing Email</DialogTitle>
<DialogContent>
@@ -810,7 +832,7 @@ const Billing = memo((props) => {
color="primary"
style={{
marginTop: !userdata.has_card_available ? 20 : 10,
borderRadius: 8,
borderRadius: 4,
height: 40,
fontSize: 16,
color: userdata.has_card_available ? "#ff8544" : "#1a1a1a",
@@ -843,7 +865,7 @@ const Billing = memo((props) => {
color="primary"
style={{
marginTop: 10,
borderRadius: 8,
borderRadius: 4,
height: 40,
fontSize: 16,
color: "#1a1a1a",
@@ -933,11 +955,19 @@ const Billing = memo((props) => {
const url = `${globalUrl}/api/v1/orgs/${selectedOrganization.id}`;
const data = {
org_id: selectedOrganization.id,
name: selectedOrganization.name,
description: selectedOrganization.description,
image: selectedOrganization.image,
defaults: selectedOrganization.defaults,
sso_config: selectedOrganization.sso_config,
mfa_required: selectedOrganization.mfa_required,
Billing: {
Consultation: {
hours: String(inputHour),
minutes: String(inputMinutes),
},
AlertThreshold: selectedOrganization.Billing.AlertThreshold,
email: selectedOrganization.Billing.email,
}
};
@@ -1030,9 +1060,9 @@ const Billing = memo((props) => {
<div style={{
padding: 20,
// maxWidth: 400,
width: 340,
width: "100%",
height: 480,
backgroundColor: hovered ? "#2b2b2b" : theme.palette.backgroundColor,
backgroundColor: hovered ? "#2b2b2b" : "#1e1e1e",
borderRadius: theme.palette?.borderRadius * 2,
border: "1px solid rgba(255,255,255,0.3)",
marginRight: 10,
@@ -1123,7 +1153,7 @@ const Billing = memo((props) => {
color="primary"
style={{
marginTop: userdata.support ? 0 : 10,
borderRadius: 8,
borderRadius: 4,
height: 40,
fontSize: 16,
color: "#1A1A1A",
@@ -1142,8 +1172,23 @@ const Billing = memo((props) => {
>
Buy
</Button>
<Dialog open={clickOnBuy} onClose={() => { setClickOnBuy(false) }} PaperProps={{style: {backgroundColor: "rgb(26, 26, 26)"}}}>
<Typography variant="body1" style={{ marginTop: 10, textAlign: 'center', padding: 20, fontSize: 18 }}>
<Dialog open={clickOnBuy} onClose={() => { setClickOnBuy(false) }} PaperProps={{
sx: {
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
border: theme?.palette?.DialogStyle?.border,
minWidth: '440px',
fontFamily: theme?.typography?.fontFamily,
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
zIndex: 1000,
'& .MuiDialogContent-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
'& .MuiDialogTitle-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
}
}}>
<Typography variant="body1" style={{ paddingTop: 10, textAlign: 'center', padding: 20, fontSize: 18, backgroundColor: theme?.palette?.DialogStyle?.backgroundColor }}>
You will be taken to Stripe to book professional service hours. You can adjust the number of hours on the left side of the Stripe page.
</Typography>
<DialogContent>
@@ -1178,10 +1223,9 @@ const Billing = memo((props) => {
color="primary"
style={{
marginTop: userdata.support ? 5 : 10,
borderRadius: 8,
borderRadius: 4,
height: 40,
fontSize: 16,
color: "#ff8544",
textTransform: 'none',
cursor: getProfessionalServices ? 'pointer' : 'not-allowed',
opacity: getProfessionalServices ? 1 : 0.6,
@@ -1202,13 +1246,23 @@ const Billing = memo((props) => {
fullWidth
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}
PaperProps={{
style: {
width: 500,
margin: 0,
sx: {
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
border: theme?.palette?.DialogStyle?.border,
minWidth: '440px',
fontFamily: theme?.typography?.fontFamily,
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
zIndex: 1000,
'& .MuiDialogContent-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
'& .MuiDialogTitle-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
}
}}
}}
>
<DialogTitle style={{ marginTop: 10, textAlign: 'center', fontWeight: 'bold' }}>
<DialogTitle style={{ paddingTop: 10, textAlign: 'center', fontWeight: 'bold' }}>
Upgrade Consultation Plan
</DialogTitle>
<DialogContent style={{ padding: '24px', }}>
@@ -1244,7 +1298,7 @@ const Billing = memo((props) => {
<Button
variant="contained"
color="primary"
style={{ marginTop: '24px', display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none' }}
style={{ marginTop: '24px', borderRadius: 4, color: "#1a1a1a", backgroundColor: "#ff8544",fontSize: 16, display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none' }}
onClick={handleUpgradeConsultation}
>
Submit Request for {consultationHours} hours
@@ -1305,8 +1359,8 @@ const Billing = memo((props) => {
padding: 20,
height: 480,
// maxWidth: 400,
width: 340,
backgroundColor: hovered ? "#2b2b2b" : theme.palette.backgroundColor,
width: "100%",
backgroundColor: hovered ? "#2b2b2b" : "#1e1e1e",
borderRadius: theme.palette?.borderRadius * 2,
border: "1px solid rgba(255,255,255,0.3)",
marginRight: 10,
@@ -1354,7 +1408,7 @@ const Billing = memo((props) => {
</li>
</ul>
</div>
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', marginTop: 30, width: 340 }}>
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', marginTop: 30, }}>
<Button
fullWidth
disabled={false}
@@ -1362,12 +1416,13 @@ const Billing = memo((props) => {
color="primary"
style={{
marginTop: 10,
borderRadius: 8,
borderRadius: 4,
height: 40,
fontSize: 16,
color: "#1A1A1A",
textTransform: 'none',
backgroundColor: "#FF8544"
backgroundColor: "#FF8544",
width: "100%",
}}
onClick={() => {
if (Cloud) {
@@ -1390,12 +1445,11 @@ const Billing = memo((props) => {
color="primary"
style={{
marginTop: 10,
borderRadius: 8,
borderRadius: 4,
height: 40,
fontSize: 16,
textTransform: 'none',
color: "#FF8544",
backgroundColor: "#1a1a1a",
width: "100%",
}}
onClick={() => {
if (Cloud) {
@@ -1417,14 +1471,23 @@ const Billing = memo((props) => {
fullWidth
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}
PaperProps={{
style: {
width: 500,
margin: 0,
backgroundColor: "rgb(26, 26, 26)",
sx: {
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
border: theme?.palette?.DialogStyle?.border,
minWidth: '440px',
fontFamily: theme?.typography?.fontFamily,
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
zIndex: 1000,
'& .MuiDialogContent-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
'& .MuiDialogTitle-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
}
}}
}}
>
<DialogTitle style={{ marginTop: 10, textAlign: 'center', fontWeight: 'bold' }}>
<DialogTitle style={{ paddingTop: 10, textAlign: 'center', fontWeight: 'bold' }}>
Private Training
</DialogTitle>
<DialogContent style={{ padding: '24px', }}>
@@ -1460,7 +1523,7 @@ const Billing = memo((props) => {
<Button
variant="contained"
color="primary"
style={{ marginTop: '24px', display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none', color: "#1a1a1a", backgroundColor: "#ff8544" }}
style={{ marginTop: '24px', fontSize: 16, display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none', color: "#1a1a1a", backgroundColor: "#ff8544" }}
onClick={handlePrivateTraining}
>
Submit Request
@@ -1819,7 +1882,6 @@ const Billing = memo((props) => {
setCurrentIndex(findCurrentIndex ? newAlertThresholds.findIndex(threshold => threshold.Email_send === false) : - 1);
toast.info("Alert Threshold deleted successfully. Don't forget to save your changes.");
};
const HandleEditOrgForAlertThreshold = (orgId) => {
// Use the `some` method to check for invalid counts
@@ -1840,6 +1902,12 @@ const Billing = memo((props) => {
const data = {
org_id: orgId,
name: selectedOrganization?.name,
description: selectedOrganization?.description,
image: selectedOrganization?.image,
defaults: selectedOrganization?.defaults,
sso_config: selectedOrganization?.sso_config,
mfa_required: selectedOrganization?.mfa_required,
billing: {
email: BillingEmail,
AlertThreshold: alertThresholds.map(threshold => ({
@@ -1847,6 +1915,7 @@ const Billing = memo((props) => {
percentage: parseInt(threshold.percentage, 10),
count: parseInt(threshold.count, 10),
})),
Consultation: selectedOrganization?.billing?.Consultation,
},
};
@@ -1901,12 +1970,12 @@ const Billing = memo((props) => {
Billing & Licensing
</Typography>}
{clickedFromOrgTab ?
<span style={{ color: "#9E9E9E" }}>{isCloud ?
<span style={{ color: "#9E9E9E", fontSize: 16 }}>{isCloud ?
"Get more out of Shuffle by adding your credit card, such as no App Run limitations, and priority support from our team. We use Stripe to manage subscriptions and do not store any of your billing information. You can manage your subscription and billing information below."
:
"Shuffle is an Open Source automation platform, and no license is required. We do however offer a Scale license with HA guarantees, along with support hours. By buying a license on https://shuffler.io, you can get access to the license immediately, and if Cloud Syncronisation is enabled, the UI in your local instance will also update."
}</span> :
<Typography variant="body1" color="textSecondary" style={{ marginTop: 0, marginBottom: 10 }}>
<Typography variant="body1" color="textSecondary" style={{ marginTop: 0, marginBottom: 10, fontSize: 16 }}>
{isCloud ?
"Get more out of Shuffle by adding your credit card, such as no App Run limitations, and priority support from our team. We use Stripe to manage subscriptions and do not store any of your billing information. You can manage your subscription and billing information below."
:
@@ -1917,19 +1986,19 @@ const Billing = memo((props) => {
{userdata.support === true ?
<div style={{ marginBottom: 10, marginTop: clickedFromOrgTab ? 16 : null, color: clickedFromOrgTab ? "#F1F1F1" : null }}>
For sales: Create&nbsp;
<a href={"https://docs.google.com/document/d/1N-ZJNn8lWaqiXITrqYcnTt53oXGLNYFEzc5PU-tdAps/copy"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
<a href={"https://docs.google.com/document/d/1N-ZJNn8lWaqiXITrqYcnTt53oXGLNYFEzc5PU-tdAps/copy"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#FF8444" }}>
EU contract
</a>
&nbsp;or&nbsp;
<a href={"https://docs.google.com/document/d/1cF-Cwxt1TcahlLrpl1GH2hFZO4gxppLeYjHW6QB0EzQ/copy"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
<a href={"https://docs.google.com/document/d/1cF-Cwxt1TcahlLrpl1GH2hFZO4gxppLeYjHW6QB0EzQ/copy"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#FF8444" }}>
NOT EU contract
</a>
&nbsp; - &nbsp;
<a href={"https://drive.google.com/drive/folders/1zVvwwkbQXW3p-DJYa0GBDzFo_ZnV_I_5"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
<a href={"https://drive.google.com/drive/folders/1zVvwwkbQXW3p-DJYa0GBDzFo_ZnV_I_5"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#FF8444" }}>
Google Drive Link
</a>
&nbsp; - &nbsp;
<a href={"https://github.com/Shuffle/Shuffle-docs/tree/master/handbook/Sales"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
<a href={"https://github.com/Shuffle/Shuffle-docs/tree/master/handbook/Sales"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#FF8444" }}>
Sales Process (old)
</a>
</div>
@@ -1944,22 +2013,24 @@ const Billing = memo((props) => {
</Typography>
: null}
<div style={{ display: "flex", width: clickedFromOrgTab ? 1030 : "auto", overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: '#494949 #2f2f2f', height: isChildOrg ? 0 : 580 }} >
<div style={{ display: "flex", width: clickedFromOrgTab ? "100%" : "auto", overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: '#494949 #2f2f2f', height: isChildOrg ? 0 : "100%", maxWidth: 860, marginTop: 20}} >
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? isChildOrg ? null :
<SubscriptionObject
index={0}
globalUrl={globalUrl}
userdata={userdata}
serverside={serverside}
billingInfo={billingInfo}
stripeKey={stripeKey}
selectedOrganization={selectedOrganization}
subscription={billingInfo.subscription}
highlight={selectedOrganization.subscriptions === undefined || selectedOrganization.subscriptions === null || selectedOrganization.subscriptions.length === 0}
<LicencePopup
serverside={serverside}
removeCookie={removeCookie}
isLoaded={isLoaded}
isLoggedIn={isLoggedIn}
globalUrl={globalUrl}
selectedOrganization={selectedOrganization}
billingInfo={billingInfo}
isCloud={isCloud}
userdata={userdata}
stripeKey={stripeKey}
{...props}
/>
: !isCloud ?
<span style={{ display: "flex", }}>
<SubscriptionObject
{/* <SubscriptionObject
index={0}
globalUrl={globalUrl}
userdata={userdata}
@@ -1977,8 +2048,22 @@ const Billing = memo((props) => {
],
}}
highlight={true}
/>
<SubscriptionObject
/> */}
<LicencePopup
{...props}
serverside={serverside}
removeCookie={removeCookie}
isLoaded={isLoaded}
isLoggedIn={isLoggedIn}
globalUrl={globalUrl}
selectedOrganization={selectedOrganization}
billingInfo={billingInfo}
isCloud={isCloud}
userdata={userdata}
stripeKey={stripeKey}
/>
{/* <SubscriptionObject
index={1}
globalUrl={globalUrl}
userdata={userdata}
@@ -1996,7 +2081,7 @@ const Billing = memo((props) => {
],
}}
highlight={false}
/>
/> */}
</span>
: null}
@@ -2255,14 +2340,14 @@ const Billing = memo((props) => {
</div>
) : null*/}
{!isChildOrg && isCloud && (
<div style={{ display: 'flex', flexDirection: 'column', marginTop: 10 }}>
<div style={{ display: 'flex', flexDirection: 'column', marginTop: 50, maxWidth: 860 }}>
<Typography style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}>
Professional Services
</Typography>
<Typography color="textSecondary" style={{fontSize: 16,}}>
We offer priority support through consultations and training to help you make the most of our product. If you have any questions, please reach out to us at support@shuffler.io.
</Typography>
<div style={{ display: 'flex', flexDirection: 'row', marginTop: 5 }}>
<div style={{ display: 'flex', flexDirection: 'row', marginTop: 5, }}>
{billingInfo.subscription !== undefined && billingInfo.subscription !== null ? (
isChildOrg ? null : (
<ConsultationManagement
@@ -2276,7 +2361,7 @@ const Billing = memo((props) => {
</div>
</div>
)}
<div style={{ marginTop: isCloud && 40, marginLeft: 10 }}>
<div style={{ marginTop: 40, marginLeft: 10 }}>
<Typography
style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}
>
@@ -2323,43 +2408,51 @@ const Billing = memo((props) => {
<div style={{ marginTop: 15 }}>
{alertThresholds.map((threshold, index) => (
<div key={index} style={{ display: 'flex', alignItems: 'center' }}>
<TextField
style={{
marginTop: 10,
backgroundColor: "#212121",
width: 250,
height: 50,
}}
InputProps={{
style: {
height: 50,
color: 'white',
},
endAdornment: '%',
}}
InputLabelProps={{
shrink: undefined,
}}
color="primary"
fullWidth
label="Alert threshold (%)"
type="number"
value={threshold.percentage}
onChange={(e) => updateAlertThreshold(index, 'percentage', e.target.value)}
margin="normal"
variant="outlined"
inputProps={{
max: 100,
}}
/>
<TextField
style={{
marginTop: 10,
backgroundColor: "#212121",
width: 250,
marginTop: 10,
height: 50,
backgroundColor: "#212121",
width: 250,
marginLeft: 15,
}}
InputProps={{
style: {
height: 50,
color: 'white',
},
endAdornment: '%',
style: {
height: 50,
color: 'white',
},
}}
color="primary"
fullWidth
label="Alert threshold (%)"
type="number"
value={threshold.percentage}
onChange={(e) => updateAlertThreshold(index, 'percentage', e.target.value)}
margin="normal"
variant="outlined"
inputProps={{
max: 100,
}}
/>
<TextField
style={{
marginTop: 10,
backgroundColor: "#212121",
width: 250,
marginLeft: 15,
}}
InputProps={{
style: {
height: 50,
color: 'white',
},
InputLabelProps={{
shrink: undefined,
}}
color="primary"
fullWidth
@@ -2370,34 +2463,67 @@ const Billing = memo((props) => {
margin="normal"
variant="outlined"
/>
<span style={{ marginLeft: alertThresholds[index].Email_send === true ? 10 : 35, color: 'green' }}>{alertThresholds[index].Email_send === true && <Tooltip title="We have already sent alert for this threshold."><CheckCircle /></Tooltip>}</span>
{
alertThresholds.length > 1 &&
(
<Button
disableRipple
disableElevation
sx={{
padding: 0,
'&:hover': {
backgroundColor: 'transparent',
},
}}
onClick={() => { setDeleteAlertVerification(true) }}
>
<DeleteIcon sx={{ color: theme.palette.secondary.main }} />
</Button>
)
}
<Dialog open={deleteAlertVerification} onClose={() => setDeleteAlertVerification(false)} sx={{ '& .MuiBackdrop-root': { backgroundColor: 'rgba(0, 0, 0, 0.3)', }, }}>
<DialogTitle>Are you sure you want to delete this threshold?</DialogTitle>
<DialogActions>
<Button style={{ textTransform: 'none', fontSize: 16 }} color="primary" onClick={() => setDeleteAlertVerification(false)}>Cancel</Button>
<Button style={{ textTransform: 'none', fontSize: 16 }} color="secondary" onClick={() => { handleDeleteAlertThreshold(index); setDeleteAlertVerification(false) }} >Delete</Button>
</DialogActions>
</Dialog>
</div>
<span
style={{
marginLeft: alertThresholds[index].Email_send === true ? 10 : 35,
color: 'green',
}}
>
{alertThresholds[index].Email_send === true && (
<Tooltip title="We have already sent alert for this threshold.">
<CheckCircle />
</Tooltip>
)}
</span>
{alertThresholds.length > 1 && (
<Button
disableRipple
disableElevation
sx={{
padding: 0,
'&:hover': {
backgroundColor: 'transparent',
},
}}
onClick={() => {
setDeleteAlertVerification(true);
setDeleteAlertIndex(index);
}}
>
<DeleteIcon sx={{ color: theme.palette.secondary.main }} />
</Button>
)}
<Dialog
open={deleteAlertVerification}
onClose={() => setDeleteAlertVerification(false)}
sx={{
'& .MuiBackdrop-root': { backgroundColor: 'rgba(0, 0, 0, 0.3)' },
}}
>
<DialogTitle>Are you sure you want to delete this threshold?</DialogTitle>
<DialogActions>
<Button
style={{ textTransform: 'none', fontSize: 16 }}
color="primary"
onClick={() => setDeleteAlertVerification(false)}
>
Cancel
</Button>
<Button
style={{ textTransform: 'none', fontSize: 16 }}
color="secondary"
onClick={() => {
handleDeleteAlertThreshold(deleteAlertIndex);
setDeleteAlertVerification(false);
}}
>
Delete
</Button>
</DialogActions>
</Dialog>
</div>
))}
</div>
</div>
@@ -2449,10 +2575,8 @@ const PaddingWrapper = memo(({ clickedFromOrgTab, children }) => {
: "auto",
padding: "27px 10px 19px 27px",
backgroundColor: '#212121',
borderRadius: '16px',
height: '100%',
boxSizing: 'border-box',
borderLeft: '1px solid #494949',
overflow: 'hidden',
maxHeight: "1700px", overflowY: "auto",scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'
}), [clickedFromOrgTab]);
+123 -29
View File
@@ -648,12 +648,13 @@ const AppStats = (defaultprops) => {
All shown statistics are gathered from <a
href={`${globalUrl}/api/v1/orgs/${selectedOrganization.id}/stats`}
target="_blank"
style={{ textDecoration: "none", color: "#f85a3e",}}
style={{ textDecoration: "none", color: "#FF8444",}}
>Your Organisation Statistics. </a>
It exists to give you more insight into your workflows, and to understand your utilization of the Shuffle platform. <b>The billing tracker is in Beta, and is always calculated manually before being invoiced.</b>
</Typography>
<div style={{display: "flex", textAlign: "center",}}>
<div style={{display: "flex", flexDirection: "column", textAlign: "center",}}>
<div style={{flexDirection: "row", }}>
{filteredStatistics !== undefined ?
<div style={{flex: 1, display: "flex", textAlign: "center",}}>
<Tooltip title={
@@ -726,40 +727,135 @@ const AppStats = (defaultprops) => {
</Tooltip>
</div>
: null}
</div>
{clickedFromOrgTab? (
<LocalizationProvider dateAdapter={AdapterDayjs} style={{ flex: 1 }}>
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
<div style={{ flex: 1, maxWidth: "200px", }}>
<div style={{ display: "flex", flexDirection: "row", width: "100%", gap: "10px", justifyContent: 'center', alignItems: 'center', paddingTop: 10 }}>
<div
style={{
display: "flex",
flexDirection: "row",
flex: 1,
alignItems: "center",
}}
>
<Typography
style={{
marginLeft: 10,
marginRight: 10,
fontSize: 16,
whiteSpace: "nowrap",
}}
color="textSecondary"
>
Search from
</Typography>
<DateTimePicker
sx={{
marginTop: 1,
marginLeft: 1,
}}
ampm={false}
label="Search from"
format="YYYY-MM-DD HH:mm:ss"
value={startTime}
onChange={handleStartTimeChange}
renderInput={(params) => <TextField {...params} />}
slotProps={{
textField: {
sx: {
"& .MuiOutlinedInput-root": {
"& fieldset": {
borderColor: "#494949 !important",
borderWidth: "1px !important",
},
"&:hover fieldset": {
borderColor: "#FFFFFF !important",
},
"&.Mui-focused fieldset": {
borderColor: "#FFFFFF !important",
},
height: "35px",
fontSize: 16,
color: "#c8c8c8",
},
},
},
}}
sx={{
"& .MuiInputBase-root": {
height: "35px",
minHeight: "35px",
},
"& .MuiInputBase-input": {
height: "35px",
padding: "0 14px",
boxSizing: "border-box",
color: "#c8c8c8",
fontSize: 16,
}
}}
ampm={false}
format="YYYY-MM-DD HH:mm:ss"
value={startTime}
onChange={handleStartTimeChange}
/>
</div>
<div style={{ flex: 1, maxWidth: "200px",}}>
</div>
<div
style={{
display: "flex",
flexDirection: "row",
flex: 1,
alignItems: "center",
}}
>
<Typography
style={{
marginLeft: 10,
marginRight: 10,
fontSize: 16,
whiteSpace: "nowrap",
}}
color="textSecondary"
>
Search until
</Typography>
<DateTimePicker
sx={{
slotProps={{
textField: {
sx: {
"& .MuiOutlinedInput-root": {
"& fieldset": {
borderColor: "#494949 !important",
borderWidth: "1px !important",
},
"&:hover fieldset": {
borderColor: "#FFFFFF !important",
},
"&.Mui-focused fieldset": {
borderColor: "#FFFFFF !important",
},
height: "35px",
fontSize: 16,
color: "#c8c8c8",
},
},
},
}}
sx={{
marginTop: 1,
marginLeft: 1,
}}
ampm={false}
label="Search until"
format="YYYY-MM-DD HH:mm:ss"
value={endTime}
onChange={handleEndTimeChange}
renderInput={(params) => <TextField {...params} />}
"& .MuiInputBase-root": {
height: "35px",
minHeight: "35px",
},
"& .MuiInputBase-input": {
height: "35px",
padding: "0 14px",
boxSizing: "border-box",
color: "#c8c8c8",
fontSize: 16,
}
}}
ampm={false}
format="YYYY-MM-DD HH:mm:ss"
value={endTime}
onChange={handleEndTimeChange}
/>
</div>
</div>
</div>
</LocalizationProvider>
</LocalizationProvider>
):(
<LocalizationProvider dateAdapter={AdapterDayjs} style={{flex: 1, }}>
<div style={{display: "flex", flexDirection: "column", }}>
@@ -794,8 +890,6 @@ const AppStats = (defaultprops) => {
</div>
</LocalizationProvider>
)}
</div>
{appRuns === undefined ?
+13 -12
View File
@@ -303,7 +303,7 @@ const CacheView = memo((props) => {
Key
<TextField
color="primary"
style={{ backgroundColor: theme.palette.inputColor }}
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor }}
autoFocus
InputProps={{
style: {
@@ -341,7 +341,7 @@ const CacheView = memo((props) => {
</div>
<TextField
color="primary"
style={{ backgroundColor: theme.palette.inputColor, marginTop: 0, }}
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor, marginTop: 0, }}
InputProps={{
style: {
color: "white",
@@ -412,7 +412,7 @@ const CacheView = memo((props) => {
</span>
</div>
<Button
style={{backgroundColor: isSelectedDataStore? "#ff8544":null, fontSize: 16, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null, color:isSelectedDataStore?"#1a1a1a":null, borderRadius:isSelectedDataStore?8:null, width:isSelectedDataStore?162:null, height:isSelectedDataStore?40:null}}
style={{backgroundColor: isSelectedDataStore? "#ff8544":null, fontSize: 16, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null, color:isSelectedDataStore?"#1a1a1a":null, borderRadius:isSelectedDataStore?4:null, width:isSelectedDataStore?162:null, height:isSelectedDataStore?40:null}}
variant="contained"
color="primary"
onClick={() =>{
@@ -425,7 +425,7 @@ const CacheView = memo((props) => {
Add Cache
</Button>
<Button
style={{ marginLeft: 5, marginRight: 15, backgroundColor: isSelectedDataStore?"#2F2F2F":null, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null,borderRadius:isSelectedDataStore?8:null, width:isSelectedDataStore?81:null, height:isSelectedDataStore?40:null, }}
style={{ marginLeft: 16, marginRight: 15, backgroundColor: isSelectedDataStore?"#2F2F2F":null, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null,borderRadius:isSelectedDataStore?4:null, width:isSelectedDataStore?81:null, height:isSelectedDataStore?40:null, }}
variant="contained"
color="primary"
onClick={() => listOrgCache(orgId)}
@@ -440,7 +440,7 @@ const CacheView = memo((props) => {
/>}
<div
style={{
borderRadius: 8,
borderRadius: 4,
marginTop: 24,
border: "1px solid #494949",
width: "100%",
@@ -450,7 +450,7 @@ const CacheView = memo((props) => {
>
<List
style={{
borderRadius: 8,
borderRadius: 4,
paddingBottom: 0,
tableLayout: "auto",
display: "table",
@@ -465,7 +465,7 @@ const CacheView = memo((props) => {
primary={header}
style={{
display: "table-cell",
padding: "0px 8px 8px 8px",
padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
@@ -518,13 +518,13 @@ const CacheView = memo((props) => {
const validate = validateJson(data.value);
return (
<ListItem key={index} style={{display:'table-row', backgroundColor: bgColor, maxHeight: 300, overflow: "auto", borderBottomLeftRadius: listCache?.length - 1 === index ? 8 : 0, borderBottomRightRadius: listCache?.length - 1 === index ? 8 : 0}}>
<ListItem key={index} style={{display:'table-row', backgroundColor: bgColor, maxHeight: 300, overflow: "auto", borderBottomLeftRadius: listCache?.length - 1 === index ? 8 : 0, borderBottomRightRadius: listCache?.length - 1 === index ? 8 : 0,}}>
<ListItemText
style={{
display: "table-cell",
overflow: "hidden",
padding: 8,
verticalAlign: "middle",
padding: "8px 8px 8px 15px"
}}
primary={data.key}
/>
@@ -533,9 +533,8 @@ const CacheView = memo((props) => {
display: "table-cell",
overflowY: "auto",
overflowX: "auto",
border: "1px solid rgba(255,255,255,0.7)",
borderRadius: 6,
backgroundColor: "#151515",
borderRadius: 4,
padding: "15px 5px",
maxHeight: 300,
verticalAlign: "middle",
}}
@@ -547,6 +546,8 @@ const CacheView = memo((props) => {
padding: 5,
maxHeight: 300,
overflowY: "auto",
backgroundColor: "#151515",
border: "1px solid rgba(255,255,255,0.7)",
}}
collapsed={true}
enableClipboard={(copy) => {
+2 -2
View File
@@ -1149,7 +1149,7 @@ const EditWorkflow = (props) => {
</div>
: null}
{/* {!isEditing ? <>
{!isEditing ? <>
<div style={{ marginTop: 20, }}>
<FormControlLabel
control={<Checkbox />}
@@ -1164,7 +1164,7 @@ const EditWorkflow = (props) => {
/>
</div>
</> : null} */}
</> : null}
<Tooltip color="primary" title={"Add more details"} placement="top">
<Button
+68 -46
View File
@@ -280,7 +280,7 @@ const Files = memo((props) => {
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
Repository URL (supported: github, gitlab, bitbucket)
<TextField
style={{ backgroundColor: theme.palette.inputColor }}
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor }}
variant="outlined"
margin="normal"
defaultValue={downloadUrl}
@@ -301,7 +301,7 @@ const Files = memo((props) => {
Branch (default value is "main"):
</span>
<TextField
style={{ backgroundColor: theme.palette.inputColor }}
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor }}
variant="outlined"
margin="normal"
defaultValue={downloadBranch}
@@ -322,7 +322,7 @@ const Files = memo((props) => {
Folder (can use / for subfolders):
</span>
<TextField
style={{ backgroundColor: theme.palette.inputColor }}
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor }}
variant="outlined"
margin="normal"
defaultValue={downloadFolder}
@@ -344,7 +344,7 @@ const Files = memo((props) => {
</span>
<div style={{ display: "flex" }}>
<TextField
style={{ flex: 1, backgroundColor: theme.palette.inputColor }}
style={{ flex: 1, backgroundColor: theme.palette.textFieldStyle.backgroundColork }}
variant="outlined"
margin="normal"
InputProps={{
@@ -360,7 +360,7 @@ const Files = memo((props) => {
fullWidth
/>
<TextField
style={{ flex: 1, backgroundColor: theme.palette.inputColor }}
style={{ flex: 1, backgroundColor: theme.palette.textFieldStyle.backgroundColor }}
variant="outlined"
margin="normal"
InputProps={{
@@ -668,7 +668,7 @@ const Files = memo((props) => {
{fileDownloadModal}
<div style={{ marginTop: isSelectedFiles ? 2: 20, marginBottom:20 }}>
<h2 style={{ display: isSelectedFiles ? null : "inline", marginTop: isSelectedFiles?0:null, marginBottom: isSelectedFiles?8:null }}>Files</h2>
<h2 style={{ display: isSelectedFiles ? null : "inline", marginTop: isSelectedFiles?0:null, marginBottom: isSelectedFiles?8:null, color: "#FFFFFF"}}>Files</h2>
<span style={{ marginLeft: isSelectedFiles ? null : 25, color:isSelectedFiles?"#9E9E9E":null}}>
Files from Workflows are a way to store as well as edit files.{" "}
<a
@@ -690,7 +690,7 @@ const Files = memo((props) => {
onClick={() => {
upload.click();
}}
style={{backgroundColor: isSelectedFiles?'#ff8544':null, color:isSelectedFiles?"#212121":null, textTransform: 'none',fontSize: 16, borderRadius:isSelectedFiles?8:null, width:isSelectedFiles?143:null, height:isSelectedFiles?35:null, boxShadow: isSelectedFiles?'none':null,}}
style={{backgroundColor: isSelectedFiles?'#ff8544':null, color:isSelectedFiles?"#212121":null, textTransform: 'none',fontSize: 16, borderRadius:isSelectedFiles?4:null, width:isSelectedFiles?143:null, height:isSelectedFiles?35:null, boxShadow: isSelectedFiles?'none':null,}}
>
Upload files
</Button>
@@ -711,7 +711,7 @@ const Files = memo((props) => {
}}
/>
<Button
style={{ marginLeft: 16, marginRight: 15, backgroundColor:isSelectedFiles?"#2F2F2F":null,borderRadius:isSelectedFiles?8:null, width:isSelectedFiles?81:null, height:isSelectedFiles?35:null, boxShadow: isSelectedFiles?'none':null, }}
style={{ marginLeft: 16, marginRight: 15, backgroundColor:isSelectedFiles?"#2F2F2F":null,borderRadius:isSelectedFiles?4:null, width:isSelectedFiles?81:null, height:isSelectedFiles?35:null, boxShadow: isSelectedFiles?'none':null, }}
variant="contained"
color="primary"
onClick={() => getFiles(selectedCategory)}
@@ -788,7 +788,7 @@ const Files = memo((props) => {
:
<Tooltip title={"Add new file category"} style={{}} aria-label={""}>
<Button
style={{ marginLeft: 5, marginRight: 15, width: 169, height: 35, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
style={{ marginLeft: 5, marginRight: 15, width: 169, height: 35, borderRadius: 4, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
color="primary"
onClick={() => {
setRenderTextBox(true);
@@ -833,12 +833,12 @@ const Files = memo((props) => {
style={{
marginTop: 20,
marginBottom: 20,
backgroundColor: theme.palette.inputColor,
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
}}
/>}
<div
style={{
borderRadius: 8,
borderRadius: 4,
marginTop: 24,
border: "1px solid #494949",
width: "100%",
@@ -862,7 +862,7 @@ const Files = memo((props) => {
primary={header}
style={{
display: "table-cell",
padding: "0px 8px 8px 8px",
padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
borderBottom: "1px solid #494949",
@@ -870,7 +870,7 @@ const Files = memo((props) => {
}}
primaryTypographyProps={{
style: {
paddingLeft: index === 3 ? 80 : 10,
paddingLeft: 10,
}
}}
/>
@@ -956,15 +956,13 @@ const Files = memo((props) => {
<ListItemText
primaryTypographyProps={{
style: {
display: 'table-cell',
maxWidth: "170px",
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
overflow: 'hidden',
padding: 8
},
padding: "8px 8px 8px 20px"
}
}}
primary={file.filename}
/>
<ListItemText
@@ -1005,6 +1003,7 @@ const Files = memo((props) => {
>
<OpenInNewIcon
style={{
width: 24, height: 24,
color:
file.workflow_id !== "global"
? "#FF8444"
@@ -1044,7 +1043,7 @@ const Files = memo((props) => {
style={{
display: 'table-cell',
overflow: "hidden",
textAlign:isSelectedFiles?"left":null,
textAlign:isSelectedFiles?"center":null,
color: file.status === "active" ? "#2BC07E" : "#FD4C62"
}}
/>
@@ -1074,7 +1073,7 @@ const Files = memo((props) => {
}}
>
<img src="/icons/editIcon.svg" alt="edit icon"
style={{color: iseditable ? "white" : "grey",}}
style={{color: iseditable ? "white" : "grey", width: 24, height: 24}}
/>
</IconButton>
</span>
@@ -1120,6 +1119,7 @@ const Files = memo((props) => {
>
<img src="/icons/downloadIcon.svg" alt="download icon"
style={{
width: 24, height: 24,
color:
file.status === "active"
? "white"
@@ -1144,7 +1144,7 @@ const Files = memo((props) => {
toast(file.id + " copied to clipboard");
}}
>
<img src="/icons/copyIcon.svg" alt="copy icon" style={{ color: "white" }} />
<img src="/icons/copyIcon.svg" alt="copy icon" style={{ color: "white", width: 24, height: 24 }} />
</IconButton>
</Tooltip>
<Tooltip
@@ -1155,21 +1155,35 @@ const Files = memo((props) => {
<span>
<IconButton
disabled={file.status !== "active"}
style = {{padding: "6px"}}
style={{ padding: "6px" }}
onClick={() => {
deleteFile(file)
deleteFile(file);
}}
>
<img src="/icons/deleteIcon.svg" alt="delete icon"
style={{
color:
file.status === "active"
? "white"
: "grey",
}}
<svg
width="24"
height="24"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
style={{
stroke: file.status === "active" ? "#fd4c62" : "#c8c8c8",
}}
>
<path
d="M5 7.20001H6.6H19.4"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
/>
<path
d="M17.7996 7.2V18.4C17.7996 18.8243 17.631 19.2313 17.331 19.5314C17.0309 19.8314 16.624 20 16.1996 20H8.19961C7.77526 20 7.3683 19.8314 7.06824 19.5314C6.76818 19.2313 6.59961 18.8243 6.59961 18.4V7.2M8.99961 7.2V5.6C8.99961 5.17565 9.16818 4.76869 9.46824 4.46863C9.7683 4.16857 10.1753 4 10.5996 4H13.7996C14.224 4 14.6309 4.16857 14.931 4.46863C15.231 4.76869 15.3996 5.17565 15.3996 5.6V7.2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
/>
</svg>
</IconButton>
</span>
</span>
</Tooltip>
</span>
style={{
@@ -1195,20 +1209,28 @@ const Files = memo((props) => {
export default memo(Files);
const DownloadFileIcon = memo(({ setLoadFileModalOpen, isSelectedFiles, }) => {
const { leftSideBarOpenByClick } = useContext(Context)
return(
<Tooltip color="primary" title={"Import files to Shuffle from Git"} placement="top">
<IconButton
color="secondary"
style={{position: "absolute", right: 0, top: isSelectedFiles?null:0, left: isSelectedFiles? leftSideBarOpenByClick ? "90%": "85%":null, transition: "left 0.3s ease" }}
variant="text"
onClick={() => setLoadFileModalOpen(true)}
>
<CloudDownloadIcon />
</IconButton>
const DownloadFileIcon = memo(({ setLoadFileModalOpen, isSelectedFiles }) => {
return (
<Tooltip color="primary" title={"Import files to Shuffle from Git"} placement="top">
<IconButton
color="secondary"
onClick={() => setLoadFileModalOpen(true)}
sx={{
position: "absolute",
right: 0,
top: isSelectedFiles ? null : 0,
left: isSelectedFiles
? "93%"
: null,
transition: "left 0.3s ease",
width: 48,
height: 48,
borderRadius: "50%",
}}
>
<CloudDownloadIcon />
</IconButton>
</Tooltip>
)
})
);
});
+50 -45
View File
@@ -229,7 +229,7 @@ useEffect(() => {
setOpenautomateTab(false);
setOpenSecurityTab(true);
setCurrentOpenTab("security");
} else if ((lastTabOpenByUser === "usecases" && currentPath.includes("/usecases2")) || currentPath.includes("/usecases2")) {
} else if ((lastTabOpenByUser === "usecases" && currentPath.includes("/usecases")) || currentPath.includes("/usecases")) {
setOpenautomateTab(true);
setOpenSecurityTab(false);
setCurrentOpenTab("usecases");
@@ -466,6 +466,7 @@ useEffect(() => {
onClick={(event) => {
handleClose();
}}
style={{fontSize: 18}}
>
<BusinessIcon style={{ marginRight: 5 }} /> Organization
</MenuItem>
@@ -475,6 +476,7 @@ useEffect(() => {
onClick={(event) => {
handleClose();
}}
style={{fontSize: 18}}
>
<SettingsIcon style={{ marginRight: 5 }} /> Account
</MenuItem>
@@ -486,6 +488,7 @@ useEffect(() => {
onClick={(event) => {
handleClose();
}}
style={{fontSize: 18}}
>
<NotificationsIcon style={{ marginRight: 5 }} /> Notifications ({
notifications === undefined || notifications === null ? 0 :
@@ -498,6 +501,7 @@ useEffect(() => {
onClick={(event) => {
handleClose();
}}
style={{fontSize: 18}}
>
<LightbulbIcon style={{ marginRight: 5 }} /> Use Cases
</MenuItem>
@@ -510,24 +514,26 @@ useEffect(() => {
onClick={(event) => {
handleClose();
}}
style={{fontSize: 18}}
>
<HelpOutlineIcon style={{ marginRight: 5 }} /> About
</MenuItem>
</Link>
<MenuItem
style={{ color: "white" }}
style={{ color: "white", fontSize: 18 }}
onClick={(event) => {
handleClickLogout();
event.preventDefault();
handleClose();
}}
>
<MeetingRoomIcon style={{ marginRight: 5 }} /> &nbsp;Logout
</MenuItem>
<Divider style={{ marginBottom: 10, }} />
<Typography variant="body2" color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, }}>
Version: 2.0.0-beta
<Typography color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, fontSize: 18 }}>
Version: 2.0.0-rc
</Typography>
</Menu>
</span>
@@ -717,6 +723,7 @@ useEffect(() => {
width: expandLeftNav ? "100%" : 30,
padding: 0,
},
fontSize: 18
};
const modalView = (
@@ -898,7 +905,7 @@ useEffect(() => {
whiteSpace: "nowrap",
}}
>
<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>K</kbd>
<kbd>Ctrl</kbd>+<kbd>K</kbd>
</span>
),
disableUnderline: true,
@@ -936,6 +943,7 @@ useEffect(() => {
display: "flex",
flexDirection: "column",
padding: expandLeftNav ? "0 16px" : "0px 8px",
gap: 1.2,
}}
>
<Box sx={{ display: "flex", flexDirection: "row", marginTop: 2.5, width: expandLeftNav ? "100%" : 48, padding: "0px", }}>
@@ -950,18 +958,18 @@ useEffect(() => {
variant="text"
style={{
...ButtonStyle,
backgroundColor: ((currentOpenTab === "automate" && currentPath.includes("/dashboards/automate"))|| (!expandLeftNav && (currentPath === "/workflows" || currentPath === "/usecases2" || currentPath.includes("/search"))))? "#2f2f2f": "transparent",
backgroundColor: ((currentOpenTab === "automate" && currentPath.includes("/dashboards/automate"))|| (!expandLeftNav && (currentPath === "/workflows" || currentPath === "/usecases" || currentPath.includes("/search"))))? "#2f2f2f": "transparent",
}}
onMouseOver={(event)=>{
event.currentTarget.style.backgroundColor = "#2f2f2f";
}}
onMouseOut={(event)=>{
event.currentTarget.style.backgroundColor = ((currentOpenTab === "automate" && currentPath.includes("/dashboards/automate"))|| (!expandLeftNav && (currentPath === "/workflows" || currentPath === "/usecases2" || currentPath.includes("/search"))))? "#2f2f2f": "transparent";
event.currentTarget.style.backgroundColor = ((currentOpenTab === "automate" && currentPath.includes("/dashboards/automate"))|| (!expandLeftNav && (currentPath === "/workflows" || currentPath === "/usecases" || currentPath.includes("/search"))))? "#2f2f2f": "transparent";
}}
>
<img
src={detectionIcon}
style={{ width: 16, height: 16, marginRight: expandLeftNav ? 10 : 0 }}
style={{ width: 18, height: 18, marginRight: expandLeftNav ? 10 : 0 }}
alt="Automate Icon"
/>
<span
@@ -1020,7 +1028,7 @@ useEffect(() => {
display: "flex",
flexDirection: "column",
paddingLeft: 16,
gap: 4,
gap: 10,
}}
>
<Link to="/usecases" style={hrefStyle}>
@@ -1032,8 +1040,9 @@ useEffect(() => {
style={{
width: "100%",
height: 35,
color: "#C8C8C8",
color: currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases") ? "#FFFFFF" : "#C8C8C8",
justifyContent: "flex-start",
fontSize: 18,
textTransform: "none",
backgroundColor: currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases")? "#2f2f2f": "transparent",
marginLeft: 16
@@ -1046,13 +1055,13 @@ useEffect(() => {
}}
disableRipple={expandLeftNav ? false : true}
>
<span style={{display: expandLeftNav ? "inline" : "none",opacity: expandLeftNav ? 1 : 0, transition: "opacity 0.3s ease", position: 'relative', left: !expandLeftNav ? 10: 0, marginRight: 10, fontSize: 16 }}></span>{" "}
<span style={{display: expandLeftNav ? "inline" : "none",opacity: expandLeftNav ? 1 : 0, transition: "opacity 0.3s ease", position: 'relative', left: !expandLeftNav ? 10: 0, marginRight: 10, fontSize: 18 }}></span>{" "}
<span
style={{
display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease",
color: currentOpenTab === "usecases" && currentPath.includes("/usecases3") ? "#F1F1F1" : "#C8C8C8",
color: currentOpenTab === "usecases" && currentPath.includes("/usecases") ? "#FFFFFF" : "#C8C8C8",
}}
>
Usecases
@@ -1068,11 +1077,12 @@ useEffect(() => {
style={{
width: "100%",
height: 35,
color: "#C8C8C8",
color: currentOpenTab === "workflows" && currentPath === "/workflows" ? "#FFFFFF" : "#C8C8C8",
justifyContent: "flex-start",
textTransform: "none",
backgroundColor: currentOpenTab === "workflows" && currentPath === "/workflows" && expandLeftNav? "#2f2f2f": "transparent",
marginLeft: 16
marginLeft: 16,
fontSize: 18
}}
disableRipple={expandLeftNav ? false : true}
onMouseOver={(event)=>{
@@ -1082,13 +1092,13 @@ useEffect(() => {
event.currentTarget.style.backgroundColor = currentOpenTab === "workflows" && currentPath === "/workflows" && expandLeftNav? "#2f2f2f": "transparent";
}}
>
<span style={{display: expandLeftNav ? "inline" : "none", opacity: expandLeftNav ? 1 : 0, transition: "opacity 0.3s ease", position: 'relative', left: !expandLeftNav ? 10: 0, marginRight: 10, fontSize: 16 }}></span>{" "}
<span style={{display: expandLeftNav ? "inline" : "none", opacity: expandLeftNav ? 1 : 0, transition: "opacity 0.3s ease", position: 'relative', left: !expandLeftNav ? 10: 0, marginRight: 10, fontSize: 18 }}></span>{" "}
<span
style={{
display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease",
color: currentOpenTab === "workflows" && currentPath === "/workflows" ? "#F1F1F1" : "#C8C8C8",
color: currentOpenTab === "workflows" && currentPath === "/workflows" ? "#FFFFFF" : "#C8C8C8",
}}
>
Workflows
@@ -1104,11 +1114,12 @@ useEffect(() => {
style={{
width: "100%",
height: 35,
color: "#C8C8C8",
color: currentOpenTab === "apps" && currentPath.includes("/apps") ? "#FFFFFF" : "#C8C8C8",
justifyContent: "flex-start",
textTransform: "none",
backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps2") ? "#2f2f2f": "transparent",
marginLeft: 16
marginLeft: 16,
fontSize: 18
}}
onMouseOver={(event)=>{
event.currentTarget.style.backgroundColor = "#2f2f2f";
@@ -1118,13 +1129,13 @@ useEffect(() => {
}}
disableRipple={expandLeftNav ? false : true}
>
<span style={{display: expandLeftNav ? "inline" : "none",opacity: expandLeftNav ? 1 : 0, transition: "opacity 0.3s ease", position: 'relative', left: !expandLeftNav ? 10: 0, marginRight: 10, fontSize: 16 }}></span>{" "}
<span style={{display: expandLeftNav ? "inline" : "none",opacity: expandLeftNav ? 1 : 0, transition: "opacity 0.3s ease", position: 'relative', left: !expandLeftNav ? 10: 0, marginRight: 10, fontSize: 18 }}></span>{" "}
<span
style={{
display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease",
color: currentOpenTab === "apps" && currentPath.includes("/apps2") ? "#F1F1F1" : "#C8C8C8",
color: currentOpenTab === "apps" && currentPath.includes("/apps") ? "#FFFFFF" : "#C8C8C8",
}}
>
Apps
@@ -1142,17 +1153,14 @@ useEffect(() => {
>
<span style={{ display: "inline-block", width: "100%" }}>
<Link
to={userdata?.support ? "/dashboards/security" : "#"}
to={"#"}
style={{
...hrefStyle,
pointerEvents: userdata?.support ? "auto" : "none",
cursor: "not-allowed",
pointerEvents: "auto",
}}
>
<Button
disabled={true}
onClick={(event) => {
if (!userdata?.support) return;
setOpenSecurityTab(true);
setOpenautomateTab(false);
setCurrentOpenTab("security");
@@ -1161,29 +1169,23 @@ useEffect(() => {
style={{
...ButtonStyle,
backgroundColor:
((currentOpenTab === "security" && currentPath.includes("/security")) ||
(!expandLeftNav &&
(currentPath.includes("detections") || currentPath.includes("response"))))
currentOpenTab === "security"
? "#2f2f2f"
: "transparent",
cursor: userdata?.support ? "pointer" : "not-allowed",
}}
onMouseOver={(event)=>{
event.currentTarget.style.backgroundColor = "#2f2f2f";
}}
onMouseOut={(event)=>{
event.currentTarget.style.backgroundColor = ((currentOpenTab === "security" && currentPath.includes("/security")) ||
(!expandLeftNav &&
(currentPath.includes("detections") || currentPath.includes("response"))))
event.currentTarget.style.backgroundColor = currentOpenTab === "security"
? "#2f2f2f"
: "transparent";
}}
disabled={!userdata?.support}
>
<ShieldOutlinedIcon
style={{
width: 16,
height: 16,
width: 18,
height: 18,
marginRight: expandLeftNav ? 10 : 0,
color: userdata?.support ? "inherit" : "#6F6F6F",
}}
@@ -1192,14 +1194,13 @@ useEffect(() => {
style={{
display: expandLeftNav ? "inline" : "none",
marginRight: "auto",
color: userdata?.support
? currentOpenTab === "security" && currentPath.includes("/security")
fontSize: 18,
color: currentOpenTab === "security"
? "#F1F1F1"
: "#C8C8C8"
: "#6F6F6F",
}}
>
Content
Discover
</span>
</Button>
</Link>
@@ -1278,7 +1279,7 @@ useEffect(() => {
}}
disabled={userdata?.support === false}
>
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 16 }}>
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
</span>
<span
@@ -1286,6 +1287,7 @@ useEffect(() => {
display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease",
fontSize: 18,
color:
userdata?.support && currentOpenTab === "detection" && currentPath.includes("/detection")
? "#F1F1F1"
@@ -1329,7 +1331,7 @@ useEffect(() => {
cursor: userdata?.support ? "pointer" : "not-allowed",
}}
>
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 16 }}>
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
</span>
<span
@@ -1337,6 +1339,7 @@ useEffect(() => {
display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease",
fontSize: 18,
color:
userdata?.support && currentOpenTab === "response" && currentPath.includes("/response")
? "#F1F1F1"
@@ -1380,7 +1383,7 @@ useEffect(() => {
cursor: userdata?.support ? "pointer" : "not-allowed",
}}
>
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 16 }}>
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
</span>
<span
@@ -1388,6 +1391,7 @@ useEffect(() => {
display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease",
fontSize: 18,
color:
userdata?.support && currentOpenTab === "response" && currentPath.includes("/response")
? "#F1F1F1"
@@ -1458,7 +1462,7 @@ useEffect(() => {
<Typography
style={{
color: "#CDCDCD",
fontSize: 14,
fontSize: 18,
padding: "8px 8px",
marginBottom: 10,
}}
@@ -1688,7 +1692,7 @@ useEffect(() => {
},
transition: "opacity 0.3s ease",
textTransform: "none",
fontSize: 16,
fontSize: 18,
}}
disableElevation
disableRipple
@@ -1718,13 +1722,14 @@ useEffect(() => {
style={{
color: "#CDCDCD",
margin: "0 5px",
fontSize: 16,
fontSize: 18,
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
maxWidth: 150,
textAlign: "center",
marginLeft: 10,
}}
>
{userdata?.username}
+213 -33
View File
@@ -24,6 +24,7 @@ import {
DialogActions,
CardContent,
ButtonGroup,
DialogContentText,
} from "@mui/material";
import { useNavigate, Link } from "react-router-dom";
@@ -42,19 +43,17 @@ import {
import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx";
import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
import Billing from "./Billing.jsx";
const LicencePopup = (props) => {
const { globalUrl, userdata, serverside, billingInfo, stripeKey, setModalOpen, isLoggedIn, isMobile } = props;
const { globalUrl, userdata, serverside, billingInfo, stripeKey, setModalOpen, isLoggedIn, isMobile, selectedOrganization, isCloud } = props;
//const alert = useAlert();
let navigate = useNavigate();
const isCloud = typeof window === 'undefined' || window === undefined || window.location === undefined ? true : window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
const [selectedDealModalOpen, setSelectedDealModalOpen] = React.useState(false);
const [dealList, setDealList] = React.useState([]);
const [dealName, setDealName] = React.useState("");
const [dealAddress, setDealAddress] = React.useState("");
const [dealType, setDealType] = React.useState("MSSP");
const [selectedOrganization, setSelectedOrganization] = React.useState({});
const [dealCountry, setDealCountry] = React.useState("United States");
const [dealCurrency, setDealCurrency] = React.useState("USD");
const [dealStatus, setDealStatus] = React.useState("initiated");
@@ -63,8 +62,8 @@ const LicencePopup = (props) => {
const [dealerror, setDealerror] = React.useState("");
const [variant, setVariant] = useState(0)
const [shuffleVariant, setShuffleVariant] = useState(isCloud ? 0 : 1)
const [BillingEmail, setBillingEmail] = useState(selectedOrganization?.Billing?.Email);
const [openChangeEmailBox, setOpenChangeEmailBox] = useState(false);
// const parsedFields = maxFields === undefined ? 300 : maxFields
const initialShuffleVariant = isCloud ? 0 : 1;
const [paymentType, setPaymentType] = useState(0)
@@ -78,6 +77,12 @@ const LicencePopup = (props) => {
const [calculatedCost, setCalculatedCost] = useState("$600")
const [selectedValue, setSelectedValue] = useState(100)
useEffect(() => {
if(selectedOrganization?.Billing?.Email !== BillingEmail) {
setBillingEmail(selectedOrganization?.Billing?.Email);
}
}, [selectedOrganization])
// Onprem
const [calculatedCores, setCalculatedCores] = useState('600')
const [onpremSelectedValue, setOnpremSelectedValue] = useState(8)
@@ -88,7 +93,7 @@ const LicencePopup = (props) => {
const paperStyle = {
padding: 20,
borderRadius: theme.palette?.borderRadius,
height: "100%",
height: "100%"
}
billingInfo.subscription = {
@@ -101,7 +106,8 @@ const LicencePopup = (props) => {
"description": "Pay as you go",
"features": [
"Basic Support",
"Limited App Runs (10.000)",
"Includes 10.000 app run/month for free. ",
"Pay for what you use with no minimum commitment and cancel anytime."
],
"limit": 10000,
}
@@ -137,13 +143,14 @@ const LicencePopup = (props) => {
})
}
const SubscriptionObject = (props) => {
const { globalUrl, index, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, subscription, highlight, } = props;
const [signatureOpen, setSignatureOpen] = React.useState(false);
const [tosChecked, setTosChecked] = React.useState(subscription.eula_signed)
const [hovered, setHovered] = React.useState(false)
const [newBillingEmail, setNewBillingEmail] = useState('');
var top_text = "Base Cloud Access"
if (subscription.limit === undefined && subscription.level === undefined || subscription.level === null || subscription.level === 0) {
subscription.name = "Enterprise"
@@ -191,6 +198,58 @@ const LicencePopup = (props) => {
// newPaperstyle.border = "1px solid #f85a3e"
}
const handleClickOpen = () => {
setOpenChangeEmailBox(true);
};
const HandleChangeBillingEmail = (orgId) => {
const email = newBillingEmail;
const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
if (!emailPattern.test(email)) {
toast("Please enter a valid email address");
return;
} else {
setNewBillingEmail(email);
}
toast("Updating billing email. Please Wait")
const data = {
org_id: orgId,
email: newBillingEmail,
billing: {
email: newBillingEmail,
},
};
const url = `${globalUrl}/api/v1/orgs/${orgId}/billing`;
fetch(url, {
method: "POST",
body: JSON.stringify(data),
credentials: "include",
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
if (response.status !== 200) {
console.log("Bad status code in get org:", response.status);
}
return response.json();
}).then((responseJson) => {
if (responseJson.success === true) {
toast.success("Successfully updated billing email");
setBillingEmail(newBillingEmail);
setOpenChangeEmailBox(false);
} else {
toast.error("Failed to update billing email. Please try again.");
}
})
.catch((error) => {
console.log("Error getting org:", error);
});
}
return (
<Tooltip
style={{ borderRadius: theme.palette?.borderRadius, }}
@@ -308,7 +367,7 @@ const LicencePopup = (props) => {
color="primary"
/>
: null}
<Typography variant="h6" style={{ marginTop: 10, marginBottom: 10, flex: 5, }}>
<Typography variant="h6" style={{ marginTop: 10, marginBottom: 10, flex: 5, whiteSpace: 'nowrap' }}>
{top_text}
</Typography>
@@ -343,7 +402,7 @@ const LicencePopup = (props) => {
</div>
<Divider />
<div>
<Typography variant="body1" style={{ marginTop: 20, }}>
<Typography variant="body1" style={{ marginTop: 20,whiteSpace: 'nowrap' }}>
{subscription.name}
</Typography>
@@ -443,21 +502,142 @@ const LicencePopup = (props) => {
})
: null}
</ul>
{isCloud ?
<span>Billing email: {selectedOrganization.org}</span>
<Typography variant="body2" color="textSecondary" style={{ marginTop: 20, marginBottom: 10 }}>
{subscription.name.includes("Scale") ?
""
:
userdata.has_card_available === true ?
"While you have a card attached to your account, Shuffle will no longer prevent workflows from running. Billing will occur at the start of each month."
:
isCloud ?
`You are not subscribed to any plan and are using the free plan with max 10,000 app runs per month. Upgrade to deactivate this limit.`
:
`You are not subscribed to any plan and are using the free, open source plan. This plan has no enforced limits, but scale issues may occur due to CPU congestion.`
}
</Typography>
{isCloud && (userdata.has_card_available === true || selectedOrganization?.Billing?.Email?.length > 0 )?
<div>
<span>Billing email: {BillingEmail}</span>
<Button
variant="contained"
onClick={handleClickOpen}
style={{
width: 'auto',
height: 20,
textTransform: 'none',
marginLeft: 'auto',
backgroundColor: 'transparent',
color: '#FF8544',
boxShadow: 'none',
border: 'none',
cursor: 'pointer',
transition: 'background-color 0.3s, color 0.3s',
}}
>
Change
</Button>
<Dialog
open={openChangeEmailBox}
onClose={()=> {setOpenChangeEmailBox(false)}}
PaperProps={{
sx: {
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
border: theme?.palette?.DialogStyle?.border,
minWidth: '440px',
fontFamily: theme?.typography?.fontFamily,
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
zIndex: 1000,
'& .MuiDialogContent-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
'& .MuiDialogTitle-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
'& .MuiDialogActions-root': {
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
},
}
}}
>
<DialogTitle style={{ fontSize: '1.5rem', fontWeight: 'bold' }}>Change Billing Email</DialogTitle>
<DialogContent>
<DialogContentText style={{ marginBottom: '20px', fontSize: 16, }}>
Enter the new billing email address.
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="email"
label="New Billing Email"
type="email"
fullWidth
value={newBillingEmail}
onKeyPress={(event) => { if (event.key === 'Enter') HandleChangeBillingEmail(selectedOrganization.id) }}
onChange={(e) => setNewBillingEmail(e.target.value)}
/>
</DialogContent>
<DialogActions>
<Button
onClick={()=> {setOpenChangeEmailBox(false)}}
color="primary"
style={{ textTransform: 'none', marginRight: '10px' }}
>
Cancel
</Button>
<Button
style={{ textTransform: 'none', backgroundColor: "#ff8544", color: "#1a1a1a" }}
onClick={(event) => HandleChangeBillingEmail(selectedOrganization.id)}
>
Save
</Button>
</DialogActions>
</Dialog>
</div>
: null}
</div>
{isCloud ? (
<Button
fullWidth
disabled={false}
color="primary"
style={{
marginTop: !userdata.has_card_available ? 20 : 10,
borderRadius: 4,
height: 40,
fontSize: 16,
color: "#1a1a1a",
backgroundColor: "#ff8544",
// backgroundImage: userdata.has_card_available ? null : "linear-gradient(to right, #f86a3e, #f34079)",
textTransform: "none",
<Button
}}
onClick={() => {
if (isCloud) {
handlePayasyougo(userdata, selectedOrganization, BillingEmail)
//navigate("/pricing?tab=cloud&highlight=true")
} else {
//window.open("https://shuffler.io/pricing?tab=onprem&highlight=true", "_blank")
handlePayasyougo()
}
}}
>
{userdata.has_card_available === true ?
"Manage Card Details"
:
"Add Card Details"
}
</Button> ) : null}
<Button
variant="outlined"
style={{
marginLeft: 115,
marginTop: 50,
borderRadius: 20,
width: 120,
color: "#FFFFFF",
marginTop: isCloud? 10 : 30,
borderRadius: 4,
width: "100%",
cursor: "pointer",
textTransform: "capitalize",
backgroundColor: "transparent",
fontSize: 16,
position: "relative", // Required for positioning tooltip
}}
title="Click to book a call"
@@ -476,7 +656,7 @@ const LicencePopup = (props) => {
// }
}}
>
<span style={{color: "#f85a3e",}}>
<span>
Book a call
</span>
<span
@@ -498,8 +678,7 @@ const LicencePopup = (props) => {
Click to book a call
</span>
</Button>
</Paper>
{/*
<div style={{ paddingRight: 150, display: "flex", alignItems: "baseline" }}>
@@ -547,14 +726,13 @@ const LicencePopup = (props) => {
}
const handleChange = (event, newValue) => {
console.log("Event, value: ", event.target, newValue)
if (shuffleVariant === 1) {
setSelectedValue(newValue)
if (newValue === 32) {
setCalculatedCost(`Get A Quote`)
} else {
setCalculatedCost(`$${newValue * 75}`)
setCalculatedCost(`$${newValue * 120}`)
}
} else {
setSelectedValue(newValue)
@@ -736,7 +914,7 @@ const LicencePopup = (props) => {
return (
<div>
<Grid container spacing={2} columns={16} style={{ flexDirection: "row", flexWrap: "nowrap", borderRadius: '16px', display: "flex" }}>
<Grid container spacing={2} columns={16} style={{ flexDirection: "row", flexWrap: "nowrap", borderRadius: '16px', display: "flex", }}>
<Grid item xs={8}>
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ?
<SubscriptionObject
@@ -895,13 +1073,11 @@ const LicencePopup = (props) => {
</div>
</div>
<div style={{ marginTop: 20, }} />
</Card>
</Grid>
</Grid>
</Grid>
<DialogActions style={{ marginTop: 15 }} >
<DialogActions style={{ marginTop: 15 }} >
<div style={{display: 'flex', flexDirection: 'column', width: "100%", justifyContent: 'space-between', gap: "10px"}}>
<Button
style={{ borderRadius: "0px", textTransform: "capitalize" }}
style={{ borderRadius: "4px", textTransform: "capitalize", width: "100%", fontSize: 16}}
variant="outlined"
onClick={() => {
if (isCloud) {
ReactGA.event({
@@ -914,7 +1090,6 @@ const LicencePopup = (props) => {
} else {
window.open("https://shuffler.io/pricing?tab=onprem", "_blank")
}
setModalOpen(false)
}}
color="primary"
>
@@ -922,7 +1097,7 @@ const LicencePopup = (props) => {
</Button>
<Button
variant="contained"
style={{ borderRadius: 20, width: 120, textTransform: "capitalize" }}
style={{ borderRadius: 4, textTransform: "capitalize", color: "#1a1a1a", backgroundColor: "#ff8544", width: "100%", fontSize: 16}}
onClick={() => {
if (isCloud) {
ReactGA.event({
@@ -948,7 +1123,12 @@ const LicencePopup = (props) => {
>
Upgrade
</Button>
</div>
</DialogActions>
</Card>
</Grid>
</Grid>
</Grid>
</div>
)
}
+40 -4
View File
@@ -141,6 +141,7 @@ const Header = (props) => {
const [subAnchorEl, setSubAnchorEl] = React.useState(null);
const [upgradeHovered, setUpgradeHovered] = React.useState(false);
const [showTopbar, setShowTopbar] = useState(false) // Set to true to show top bar
const [selectedOrganization, setSelectedOrganization] = useState({});
const stripeKey = typeof window === 'undefined' || window.location === undefined ? "" : window.location.origin === "https://shuffler.io" ? "pk_live_51PXYYMEJjT17t98N20qEqItyt1fLQjrnn41lPeG2PjnSlZHTDNKHuisAbW00s4KAn86nGuqB9uSVU4ds8MutbnMU00DPXpZ8ZD" : "pk_test_51PXYYMEJjT17t98NbDkojZ3DRvsFUQBs35LGMx3i436BXwEBVFKB9nCvHt0Q3M4MG3dz4mHheuWvfoYvpaL3GmsG00k1Rb2ksO"
let navigate = useNavigate();
const classes = useStyles();
@@ -222,10 +223,45 @@ const Header = (props) => {
window.location.host === "shuffler.io" ||
window.location.host === "localhost:5002";
const curpath = (typeof window !== "undefined" && window.location && typeof window.location.pathname === "string")
? window.location.pathname
: "";
const handleGetOrg = (orgId) => {
fetch(`${globalUrl}/api/v1/orgs/${orgId}`, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
if (response.status === 401) {
}
return response.json();
})
.then((responseJson) => {
if (responseJson["success"] === false) {
console.log("Error getting org: ", responseJson);
} else {
setSelectedOrganization(responseJson);
}
})
.catch((error) => {
console.log("Error getting org: ", error);
});
};
useEffect(() => {
if (isLoggedIn && userdata?.active_org?.id?.length > 0) {
handleGetOrg(userdata.active_org.id);
}
}, [isLoggedIn]);
// DEBUG HERE
const handleClickLogout = () => {
console.log("SHOULD LOG OUT");
@@ -441,7 +477,7 @@ const Header = (props) => {
})
</MenuItem>
</Link>
<Link to="/usecases2" style={hrefStyle}>
<Link to="/usecases" style={hrefStyle}>
<MenuItem
onClick={(event) => {
handleClose();
@@ -537,9 +573,9 @@ const Header = (props) => {
isLoaded={isLoaded}
isLoggedIn={isLoggedIn}
globalUrl={globalUrl}
selectedOrganization={selectedOrganization}
billingInfo={billingInfo}
isCloud={isCloud}
userdata={userdata}
stripeKey={stripeKey}
setModalOpen={setModalOpen}
@@ -590,7 +626,7 @@ const Header = (props) => {
</List>
<List className={classes.menuList} component="nav">
<ListItem style={{ textAlign: "center", marginLeft: "0px" }}>
<Link to="/usecases2" style={hrefStyle}>
<Link to="/usecases" style={hrefStyle}>
<Button
variant="text"
color="secondary"
+111 -56
View File
@@ -255,7 +255,7 @@ const Priorities = memo((props) => {
onClick={() => {
clearNotifications()
}}
style={{marginLeft: 50, }}
style={{marginLeft: 50, textTransform: "none", fontSize: 16}}
>
Mark all as read
</Button>
@@ -265,7 +265,7 @@ const Priorities = memo((props) => {
{clickedFromOrgTab? null : <Divider style={{marginTop: 50, marginBottom: 50, }} />}
<h2 style={{ display: clickedFromOrgTab ? null:"inline", marginBottom: clickedFromOrgTab ? 8:null, marginTop: clickedFromOrgTab ? 30 :null, color: clickedFromOrgTab ? "#ffffff" : null }}>Suggestions</h2>
<span style={{ fontSize: 16, color: clickedFromOrgTab ?"#9E9E9E":null,marginLeft: clickedFromOrgTab ?null:25 }}>
<span style={{ fontSize: 16, color: clickedFromOrgTab ?"#9E9E9E":null,marginLeft: clickedFromOrgTab ?null:25, }}>
Suggestions are tasks identified by Shuffle to help you discover ways to protect your and customers' company. <br/>These range from simple configurations in Shuffle to Usecases you may have missed.&nbsp;
<a
target="_blank"
@@ -409,8 +409,8 @@ const NotificationItem = memo((props) => {
{data.read === false ?
<Chip
label={"Unread"}
variant="outlined"
color="primary"
variant="contained"
color="secondary"
style={{marginRight: 15, height: 25, }}
/>
:
@@ -431,64 +431,119 @@ const NotificationItem = memo((props) => {
:
null
}
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, maxHeight: 200, overflowX: "hidden", overflowY: "auto", wordWrap: "break-word" }}>
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, maxHeight: 200, overflowX: "hidden", overflowY: "auto", wordWrap: "break-word", fontSize: 16 }}>
{data.description}
</Typography >
<div style={{ display: "flex" }}>
<ButtonGroup>
<Button
color="secondary"
variant="outlined"
style={{ marginTop: 15 }}
disabled={data.reference_url === undefined || data.reference_url === null || data.reference_url.length === 0}
onClick={() => {
window.open(data.reference_url, "_blank")
}}
>
Explore
</Button>
{data.read === false ? (
<Button
color="secondary"
variant="outlined"
style={{ marginTop: 15 }}
onClick={() => {
dismissNotification(data.id);
}}
>
Dismiss
</Button>
) : null}
<Tooltip title="Disabling a notification makes it so similar notifications to this one will NOT be re-opened. It will NOT forward notifications to your notification workflow, but WILL still keep counting." placement="top">
<Button
color="secondary"
variant={data.ignored === true ? "contained" : "outlined"}
style={{ marginTop: 15, }}
onClick={() => {
if (data.ignored === true) {
dismissNotification(data.id, false)
} else {
dismissNotification(data.id, true)
}
}}
>
{data.ignored === true ? "Re-enable" : "Disable"}
</Button>
</Tooltip>
</ButtonGroup>
<ButtonGroup style={{marginTop: 15, minHeight: 50, maxHeight: 50, }}>
<Button
style={{
textTransform: "none",
border: "1px solid #ff8544",
color: "#ff8544",
opacity: data.reference_url ? 1 : 0.5,
cursor: data.reference_url ? "pointer" : "not-allowed",
}}
disabled={
!data.reference_url || data.reference_url.length === 0
}
onClick={() => {
window.open(data.reference_url, "_blank");
}}
>
Explore
</Button>
<Typography variant="body2" color="textSecondary" style={{ marginLeft: 20, marginTop: 20, wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis" }}>
<b>First seen</b>: {new Date(data.created_at * 1000).toISOString().slice(0, 19)}
</Typography >
{data.read === false ? (
<Button
variant="outlined"
color="secondary"
style={{
height: 50,
}}
onClick={() => {
dismissNotification(data.id);
}}
>
Mark Read
</Button>
) : null}
<Typography variant="body2" color="textSecondary" style={{ marginLeft: 20, marginTop: 20, wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis" }}>
<b>Last seen</b>: {new Date(data.updated_at * 1000).toISOString().slice(0, 19)}
</Typography >
<Tooltip
title="Disabling a notification makes it so similar notifications to this one will NOT be re-opened. It will NOT forward notifications to your notification workflow, but WILL still keep counting."
placement="top"
>
<Button
variant="outlined"
color="secondary"
style={{
textTransform: "none",
opacity: data.ignored || data.dismissable ? 1 : 0.5,
cursor: data.dismissable ? "pointer" : "not-allowed",
}}
disabled={!data.dismissable}
onClick={() => {
if (data.ignored) {
dismissNotification(data.id, false);
} else {
dismissNotification(data.id, true);
}
}}
>
{data.ignored ? "Re-enable" : "Disable"}
</Button>
</Tooltip>
</ButtonGroup>
<Typography
variant="body2"
color="textSecondary"
style={{
marginLeft: 20,
marginTop: 20,
wordWrap: "break-word",
overflow: "hidden",
textOverflow: "ellipsis",
fontSize: 16,
}}
>
<b>First seen</b>:{" "}
{new Date(data.created_at * 1000).toISOString().slice(0, 19)}
</Typography>
<Typography
variant="body2"
color="textSecondary"
style={{
marginLeft: 20,
marginTop: 20,
wordWrap: "break-word",
overflow: "hidden",
textOverflow: "ellipsis",
fontSize: 16,
}}
>
<b>Last seen</b>:{" "}
{new Date(data.updated_at * 1000).toISOString().slice(0, 19)}
</Typography>
<Typography
variant="body2"
color="textSecondary"
style={{
marginLeft: 20,
marginTop: 20,
wordWrap: "break-word",
overflow: "hidden",
textOverflow: "ellipsis",
fontSize: 16,
}}
>
<b>Times seen</b>: {data.amount}
</Typography>
</div>
<Typography variant="body2" color="textSecondary" style={{ marginLeft: 20, marginTop: 20, wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis" }}>
<b>Times seen</b>: {data.amount}
</Typography >
</div>
</Paper>
);
})
+1 -1
View File
@@ -154,7 +154,7 @@ const Priority = (props) => {
}
</div>
<div style={{flex: 1, display: "flex", marginLeft: 30, }}>
<Button style={{height: 50, borderRadius: 25, fontSize:16, boxShadow: clickedFromOrgTab ? "none":null,textTransform: clickedFromOrgTab ? 'capitalize':null, marginTop: 8, width: 175, marginRight: 10, color: priority.active === false ? "white" :clickedFromOrgTab ?"#FF8444": "black", backgroundColor: priority.active === false ? theme.palette.inputColor :clickedFromOrgTab?"rgba(255, 132, 68, 0.2)":"rgba(255,255,255,0.8)", }} variant="contained" color="secondary" onClick={() => {
<Button style={{height: 50, borderRadius: 4, fontSize:16, boxShadow: clickedFromOrgTab ? "none":null,textTransform: clickedFromOrgTab ? 'capitalize':null, marginTop: 8, width: 175, marginRight: 10, color: priority.active === false ? "white" :clickedFromOrgTab ?"#ff8544": "black", backgroundColor: priority.active === false ? theme.palette.inputColor :clickedFromOrgTab?"transparent":"rgba(255,255,255,0.8)", border: "1px solid #ff8544"}} variant="contained" color="secondary" onClick={() => {
if (isCloud) {
ReactGA.event({
+3 -2
View File
@@ -238,7 +238,7 @@ const Admin2 = (props) => {
const data = {
name: name,
description: description,
org_id: orgId,
org_id: orgId?.length > 0 ? orgId : selectedOrganization?.id,
image: image,
defaults: defaults,
sso_config: sso_config,
@@ -263,6 +263,7 @@ const Admin2 = (props) => {
if (responseJson["success"] === false) {
toast("Failed updating org: ", responseJson.reason);
} else {
handleGetOrg(selectedOrganization?.id);
if (
lead_info === undefined ||
lead_info === null ||
@@ -329,7 +330,7 @@ const Admin2 = (props) => {
}
return (
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: 29, zoom: 0.8, }}>
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: 29, zoom: 0.9}}>
<AdminNavBar userdata={userdata} isLoaded={isLoaded} selectedStatus={selectedStatus} setSelectedStatus={setSelectedStatus} selectedTab={selectedTab} orgId={selectedOrganization.id} handleStatusChange={handleStatusChange} handleEditOrg={handleEditOrg} handleGetOrg={handleGetOrg} setSelectedOrganization={setSelectedOrganization} selectedOrganization={selectedOrganization} setNotifications={setNotifications} stripeKey={stripeKey} notifications={notifications} checkLogin={checkLogin} globalUrl={globalUrl} isCloud={isCloud} serverside={serverside} />
</div>
);
+50 -37
View File
@@ -4859,7 +4859,7 @@ const releaseToConnectLabel = "Release to Connect"
// This causes memory referencing to become a nightmare
const data = event.target.data()
if (data.app_name === "Shuffle Workflow") {
if ((data.parameters !== undefined) && (data.parameters.length > 0)) {
if ((data?.parameters !== undefined) && (data?.parameters?.length > 0)) {
getWorkflowApps(data.parameters[0].value)
}
}
@@ -10657,7 +10657,7 @@ const releaseToConnectLabel = "Release to Connect"
return(
<div style={{marginLeft: index !== 0 ? 5 : 0, }}>
<div key={index} style={{marginLeft: index !== 0 ? 5 : 0, }}>
<ParsedAppPaper small={true} action={trigger.name} app={JSON.parse(JSON.stringify(trigger))} />
</div>
)
@@ -11200,7 +11200,7 @@ const releaseToConnectLabel = "Release to Connect"
const minSize = 370
var rightsidebarStyle = {
position: "fixed",
top: appBarSize - 35,
top: workflow?.public && !isLoggedIn ? 100 : showWorkflowRevisions ? 100 : appBarSize - 35,
right: 25,
height: "90vh",
maxWidth: 600,
@@ -13218,7 +13218,7 @@ const releaseToConnectLabel = "Release to Connect"
};
if (Object.getOwnPropertyNames(selectedTrigger).length > 0) {
if (Object.getOwnPropertyNames(selectedTrigger)?.length > 0) {
if (workflow.triggers[selectedTriggerIndex] === undefined) {
return null;
}
@@ -14378,7 +14378,7 @@ const releaseToConnectLabel = "Release to Connect"
// Special SCHEDULE handler
var trigger_header_auth = ""
if (Object.getOwnPropertyNames(selectedTrigger).length > 0 && workflow.triggers !== null && workflow.triggers !== undefined && workflow.triggers.length >= selectedTriggerIndex && workflow.triggers[selectedTriggerIndex] !== undefined ) {
if (Object.getOwnPropertyNames(selectedTrigger)?.length > 0 && workflow?.triggers !== null && workflow?.triggers !== undefined && workflow?.triggers?.length >= selectedTriggerIndex && workflow?.triggers[selectedTriggerIndex] !== undefined ) {
if (selectedTrigger.trigger_type === "SCHEDULE" && workflow.triggers[selectedTriggerIndex].parameters === undefined || workflow.triggers[selectedTriggerIndex].parameters === null) {
console.log("Autofixing schedule")
@@ -14447,7 +14447,7 @@ const releaseToConnectLabel = "Release to Connect"
if (
workflow.triggers[selectedTriggerIndex].parameters === undefined ||
workflow.triggers[selectedTriggerIndex].parameters === null ||
workflow.triggers[selectedTriggerIndex].parameters.length === 0
workflow?.triggers[selectedTriggerIndex]?.parameters?.length === 0
) {
workflow.triggers[selectedTriggerIndex].parameters = [];
workflow.triggers[selectedTriggerIndex].parameters[0] = {
@@ -14485,7 +14485,7 @@ const releaseToConnectLabel = "Release to Connect"
}
}
const WebhookSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "WEBHOOK" ? null :
const WebhookSidebar =!selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || workflow?.triggers[selectedTriggerIndex] === undefined || selectedTrigger?.trigger_type !== "WEBHOOK" ? null :
<div style={appApiViewStyle}>
<h3 style={{ marginBottom: "5px" }}>
{selectedTrigger.app_name}: {selectedTrigger.status}
@@ -14752,8 +14752,8 @@ const releaseToConnectLabel = "Release to Connect"
</div>
<TextField
style={{
backgroundColor: theme.palette.inputColor,
borderRadius: theme.palette?.borderRadius,
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
borderRadius: theme.palette.textFieldStyle.borderRadius,
}}
id="webhook_uri_field"
onClick={() => {
@@ -15217,7 +15217,7 @@ const releaseToConnectLabel = "Release to Connect"
})
}
const UserinputSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "USERINPUT" ? null :
const UserinputSidebar = !selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || !workflow?.triggers[selectedTriggerIndex] || !selectedTrigger.trigger_type || selectedTrigger.trigger_type !== "USERINPUT" ? null :
<div style={appApiViewStyle}>
<h3 style={{ marginBottom: "5px" }}>
{selectedTrigger.app_name}
@@ -15378,7 +15378,13 @@ const releaseToConnectLabel = "Release to Connect"
label={<div style={{ color: "white" }}>SMS</div>}
/>
</FormGroup>
{workflow.triggers[selectedTriggerIndex].parameters[2] !== undefined && workflow.triggers[selectedTriggerIndex].parameters[2].value.includes("subflow") ? (
{workflow?.triggers &&
workflow?.triggers[selectedTriggerIndex] &&
workflow?.triggers[selectedTriggerIndex].parameters &&
workflow?.triggers[selectedTriggerIndex].parameters[2] &&
workflow?.triggers[selectedTriggerIndex].parameters[2].value &&
workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("subflow")
? (
<div style={{ }}>
{workflows === undefined ||
workflows === null ||
@@ -15506,9 +15512,13 @@ const releaseToConnectLabel = "Release to Connect"
</div>
) : null}
{workflow.triggers[selectedTriggerIndex].parameters[2] !==
undefined &&
workflow.triggers[selectedTriggerIndex].parameters[2].value.includes("email") ? (
{workflow?.triggers &&
workflow?.triggers[selectedTriggerIndex] &&
workflow?.triggers[selectedTriggerIndex].parameters &&
workflow?.triggers[selectedTriggerIndex].parameters[2] &&
workflow?.triggers[selectedTriggerIndex].parameters[2].value &&
workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("email")
? (
<TextField
style={{
backgroundColor: theme.palette.inputColor,
@@ -15538,11 +15548,15 @@ const releaseToConnectLabel = "Release to Connect"
/>
) : null}
{workflow.triggers[selectedTriggerIndex].parameters[2] !==
undefined &&
workflow.triggers[
selectedTriggerIndex
].parameters[2].value.includes("sms") ? (
{workflow?.triggers &&
workflow?.triggers[selectedTriggerIndex] &&
workflow?.triggers[selectedTriggerIndex].parameters &&
workflow?.triggers[selectedTriggerIndex].parameters[2] &&
workflow?.triggers[selectedTriggerIndex].parameters[2].value &&
(
workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("email") ||
workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("sms")
) ? (
<TextField
style={{
backgroundColor: theme.palette.inputColor,
@@ -15639,7 +15653,7 @@ const releaseToConnectLabel = "Release to Connect"
selectedTrigger.environment = defaultEnvironment.Name
setSelectedTrigger(selectedTrigger) }
const PipelineSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined && selectedTrigger.trigger_type !== "SCHEDULE" ? null :
const PipelineSidebar = !selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || !workflow?.triggers[selectedTriggerIndex] || !selectedTrigger.trigger_type || selectedTrigger.trigger_type !== "SCHEDULE" ? null :
<div style={appApiViewStyle}>
<h3 style={{ marginBottom: "5px" }}>
{selectedTrigger.app_name}: {selectedTrigger.status}
@@ -15901,7 +15915,7 @@ const releaseToConnectLabel = "Release to Connect"
</div>
</div>
const ScheduleSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined && selectedTrigger.trigger_type !== "SCHEDULE" ? null :
const ScheduleSidebar = !selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || !workflow?.triggers[selectedTriggerIndex] && (!selectedTrigger.trigger_type || selectedTrigger.trigger_type !== "SCHEDULE") ? null :
<div style={appApiViewStyle}>
<h3 style={{ marginBottom: "5px" }}>
{selectedTrigger.app_name}: {selectedTrigger.status}
@@ -16158,9 +16172,8 @@ const releaseToConnectLabel = "Release to Connect"
position: "absolute",
top: isMobile ? 30 : 25,
left: isMobile ? 20 : leftSideBarOpenByClick ? leftBarSize + 275 : leftBarSize+135,
transition: "left 0.3s ease",
transform: isMobile ? "translateX(20px)" : `translateX(${leftBarSize}px)`,
transition: "all 0.3s ease",
zoom: 0.9,
}
@@ -16922,7 +16935,7 @@ const releaseToConnectLabel = "Release to Connect"
border: "1px solid rgba(255,255,255,0.1)",
position: "absolute",
bottom: 100,
left: leftSideBarOpenByClick ? leftBarSize+300 : leftBarSize+115,
left: leftSideBarOpenByClick ? leftBarSize+270 : leftBarSize+115,
color: "white",
padding: 10,
@@ -17374,8 +17387,8 @@ const releaseToConnectLabel = "Release to Connect"
color="secondary"
variant="text"
style={{
height: workflow.public ? 100 : buttonHeights,
width: workflow.public ? 100 : 64,
height: buttonHeights,
width: 64,
}}
variant={
lastSaved && !workflow.public ? "text" : "contained"
@@ -17619,7 +17632,7 @@ const releaseToConnectLabel = "Release to Connect"
defaultReturn = <CommentSidebar />
} else if (Object.getOwnPropertyNames(selectedTrigger).length > 0) {
if (selectedTrigger.trigger_type === undefined) {
//defaultReturn = <UserinputSidebar />
// defaultReturn = <UserinputSidebar />
return null;
} else {
/*
@@ -17776,7 +17789,7 @@ const releaseToConnectLabel = "Release to Connect"
<Typography variant="body1" style={{ marginRight: 10, }}>
Tags
</Typography>
<div style={{ display: "flex" }}>
<div style={{ display: "flex", flexWrap: 'wrap', gap: 5, }}>
{workflow.tags.map((tag, index) => {
if (index >= 3) {
return null;
@@ -17958,9 +17971,8 @@ const releaseToConnectLabel = "Release to Connect"
</Typography>
<Button
color="primary"
variant="contained"
fullWidth
style={{ marginTop: 15, }}
style={{ marginTop: 15, backgroundColor: "#ff8544", color: "#1a1a1a", fontSize: 16, textTransform: "none" }}
onClick={() => {
// Further checks are being done on the backend
// Even if the user can "edit" a workflow on the frontend,
@@ -17990,7 +18002,7 @@ const releaseToConnectLabel = "Release to Connect"
variant="outlined"
disabled={workflow.public !== true}
fullWidth
style={{ marginTop: 15, }}
style={{ marginTop: 15, textTransform: "none", fontSize: 16}}
onClick={() => {
// setEditWorkflowDetails(true)
// workflow.public = false
@@ -20554,7 +20566,7 @@ const releaseToConnectLabel = "Release to Connect"
);
const newView = (
<div style={{ color: "white", marginLeft: leftSideBarOpenByClick ? 280 : 100, transition: "margin-left 0.3s ease", }}>
<div style={{ color: "white", marginLeft: leftSideBarOpenByClick ? workflow?.public ? 210 : 250 : workflow?.public ? isLoggedIn ? 60 : 0 : isLoggedIn ? 100 : 0, transition: "margin-left 0.3s ease", overflow: 'hidden' }}>
<div
style={{ display: "flex", borderTop: "0px solid rgba(91, 96, 100, 1)" }}
>
@@ -20590,8 +20602,8 @@ const releaseToConnectLabel = "Release to Connect"
maxZoom={2.0}
wheelSensitivity={0.25}
style={{
width: cytoscapeWidth,
height: bodyHeight - 5,
width: workflow?.public && !isLoggedIn ? cytoscapeWidth + 50 : cytoscapeWidth ,
height: workflow?.public && !isLoggedIn ? (bodyHeight - 50) : bodyHeight - 2,
backgroundColor: theme.palette.surfaceColor,
}}
stylesheet={cystyle}
@@ -20678,7 +20690,7 @@ const releaseToConnectLabel = "Release to Connect"
{/* Most important: Actions. But these are a lot more complex */}
{rightSideBarOpen && (selectedTrigger.trigger_type === "SCHEDULE" || selectedTrigger.trigger_type === "WEBHOOK" || selectedTrigger.trigger_type === "PIPELINE" || selectedTrigger.trigger_type === "USERINPUT") ?
<div id="rightside_actions" style={rightsidebarStyle}>
{Object.getOwnPropertyNames(selectedTrigger).length > 0 ?
{Object.getOwnPropertyNames(selectedTrigger)?.length > 0 ?
selectedTrigger.trigger_type === "SCHEDULE" ?
ScheduleSidebar
: selectedTrigger.trigger_type === "PIPELINE" ?
@@ -20693,7 +20705,7 @@ const releaseToConnectLabel = "Release to Connect"
: null}
{
rightSideBarOpen && selectedTrigger.trigger_type === "SUBFLOW"&& Object.getOwnPropertyNames(selectedTrigger).length > 0 ?
rightSideBarOpen && selectedTrigger?.trigger_type === "SUBFLOW"&& Object.getOwnPropertyNames(selectedTrigger)?.length > 0 ?
<div id="rightside_actions" style={rightsidebarStyle}>
<SubflowSidebar/>
</div> : null
@@ -22033,6 +22045,7 @@ const releaseToConnectLabel = "Release to Connect"
<Paper
style={{padding: "15px 15px 15px 25px", minHeight: 105, maxHeight: 105, cursor: "pointer", backgroundColor: newrevision.edited === selectedVersion.edited ? "rgba(255,255,255,0.3)" : theme.palette.surfaceColor, border: showBorder === true ? `1px solid ${green}` : "1px solid rgba(255,255,255,0.3)", marginBottom: 10,
}} onClick={(e) => {
setRightSideBarOpen(false)
if (newrevision.edited === selectedVersion.edited) {
console.log("Same revision! No setting.")
return
+7 -4
View File
@@ -64,6 +64,7 @@ const inputColor = "#383B40";
const bodyDivStyle = {
margin: "auto",
width: "900px",
zoom: 0.8,
};
const actionListStyle = {
@@ -72,10 +73,11 @@ const actionListStyle = {
paddingBottom: "10px",
paddingTop: "10px",
marginTop: "5px",
backgroundColor: inputColor,
display: "flex",
color: "white",
position: "relative",
position: "relative",
backgroundColor: theme.palette.platformColor,
};
const boxStyle = {
@@ -89,7 +91,8 @@ const boxStyle = {
paddingTop: "30px",
display: "flex",
flexDirection: "column",
backgroundColor: surfaceColor,
backgroundColor: theme.palette.backgroundColor,
};
const dividerStyle = {
@@ -6191,7 +6194,7 @@ const AppCreator = (defaultprops) => {
{testView}
*/}
<div style={{height: 50, padding: 25, display: "flex", marginTop: 35, position: "fixed", bottom: 0, left: 0, width: "100%", backgroundColor: theme.palette?.backgroundColor, borderTop: "1px solid rgba(255,255,255,0.3)",}}>
<div style={{height: 50, padding: 15, display: "flex", marginTop: 35, position: "fixed", bottom: 0, left: 0, width: "100%", backgroundColor: theme.palette?.backgroundColor, borderTop: "1px solid rgba(255,255,255,0.3)",}}>
<div style={{width: 450, margin: "auto", display: "flex", textAlign: "center", }}>
{appDownloadData.length > 0 ?
<Tooltip title="Download the OpenAPI specification for the App" placement="bottom">
+141 -83
View File
@@ -20,14 +20,18 @@ import {
IconButton,
} from "@mui/material";
import { Context } from "../context/ContextApi.jsx";
import Add from '@mui/icons-material/Add';
import CachedIcon from '@mui/icons-material/Cached';
import CloudDownloadIcon from '@mui/icons-material/CloudDownload';
import EditIcon from '@mui/icons-material/Edit';
import {
Add as AddIcon,
Edit as EditIcon,
Search as SearchIcon,
Clear as ClearIcon,
Close as CloseIcon,
Cached as CachedIcon,
CloudDownload as CloudDownloadIcon,
} from "@mui/icons-material";
import InputAdornment from '@mui/material/InputAdornment';
import Search from '@mui/icons-material/Search';
import ClearIcon from '@mui/icons-material/Clear';
import CloseIcon from '@mui/icons-material/Close';
import { ClearRefinements, connectHits, connectSearchBox, connectStateResults, InstantSearch, RefinementList, connectRefinementList, Configure } from "react-instantsearch-dom";
import { removeQuery } from "../components/ScrollToTop.jsx";
@@ -45,7 +49,7 @@ const searchClient = algoliasearch(
);
// AppCard Component
const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes, currTab, handleAppClick, leftSideBarOpenByClick, userdata }) => {
const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes, currTab, handleAppClick, leftSideBarOpenByClick, userdata, fetchApps }) => {
const navigate = useNavigate();
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "localhost:3000";
const appUrl = isCloud ? `/apps/${data.id}` : `https://shuffler.io/apps/${data.id}`;
@@ -117,9 +121,17 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
fontWeight: 600,
whiteSpace: "nowrap",
marginLeft: 8,
maxWidth: "90%",
gap: 8
}}>
{data.name.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase())}
<div style={{
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
color: '#F1F1F1'
}}>
{data.name.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase())}
</div>
</div>
<div style={{
overflow: "hidden",
@@ -182,12 +194,13 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
<Button
className="deactivate-button"
sx={{
width: 102,
width: 110,
height: 35,
borderRadius: 0.75,
bgcolor: "rgba(73, 73, 73, 1)",
color: "rgba(241, 241, 241, 1)",
textTransform: "none",
fontSize: 16,
fontFamily: theme?.typography?.fontFamily,
transition: "background-color 0.3s ease",
"&:hover": {
@@ -213,6 +226,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
toast.error(responseJson.reason);
} else {
toast.success("App Deactivated Successfully.");
fetchApps();
}
})
.catch(error => {
@@ -445,13 +459,21 @@ const Hits = ({
overflow: "hidden",
gap: 8,
fontWeight: 600,
maxWidth: "90%",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
color: '#F1F1F1'
}}
>
{(allActivatedAppIds && allActivatedAppIds.includes(data.objectID)) && <Box sx={{ width: 8, height: 8, backgroundColor: "#02CB70", borderRadius: '50%' }} />}
{normalizedString(data.name)}
<div style={{
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
color: '#F1F1F1'
}}>
{normalizedString(data.name)}
</div>
</div>
<div
@@ -535,18 +557,19 @@ const Hits = ({
paddingRight: 10,
minWidth: 110
}}>
{hoverEffect === index && isCloud && (
{hoverEffect === index && (
<div>
{allActivatedAppIds && allActivatedAppIds.includes(data.objectID) ? (
<Button
style={{
width: 102,
width: 110,
height: 35,
borderRadius: 3,
borderRadius: 4,
backgroundColor: "rgba(73, 73, 73, 1)",
color: "rgba(241, 241, 241, 1)",
textTransform: "none",
fontFamily: theme?.typography?.fontFamily,
fontSize: 16,
}}
onClick={(event) => {
handleActivateButton(event, data, "deactivate");
@@ -560,9 +583,10 @@ const Hits = ({
color: "black",
width: 102,
height: 35,
borderRadius: 3,
borderRadius: 4,
textTransform: "none",
fontFamily: theme?.typography?.fontFamily,
fontSize: 16
}}
onClick={(event) => {
handleActivateButton(event, data, "activate");
@@ -655,15 +679,15 @@ const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
event.preventDefault();
}
}}
style={{ borderRadius: 8, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1 }}
style={{ borderRadius: 4, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1 }}
InputProps={{
style: {
borderRadius: 8,
borderRadius: 4,
height: 45
},
endAdornment: (
<InputAdornment position="end">
{localQuery?.length === 0 ? <Search /> : (
{localQuery?.length === 0 ? <SearchIcon /> : (
<ClearIcon
style={{
cursor: "pointer",
@@ -703,7 +727,7 @@ const CategoryDropdown = ({ items, currentRefinement, refine }) => {
onChange={handleChange}
displayEmpty
multiple
style={{ borderRadius: 8, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1 }}
style={{ borderRadius: 4, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1 }}
renderValue={(selected) => {
if (selected.length === 0) return 'All Categories';
return (
@@ -764,7 +788,7 @@ const LabelDropdown = ({ items, currentRefinement, refine }) => {
onChange={handleChange}
displayEmpty
multiple
style={{ borderRadius: 8, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1 }}
style={{ borderRadius: 4, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1 }}
renderValue={(selected) => {
if (selected.length === 0) return 'All Labels';
return (
@@ -855,7 +879,7 @@ const AppSkeleton = () => {
backgroundColor: "#212121",
width: "100%",
height: 120,
borderRadius: 8,
borderRadius: 4,
}}>
<div style={{
display: "flex",
@@ -868,7 +892,7 @@ const AppSkeleton = () => {
width={100}
height={90}
style={{
borderRadius: 6,
borderRadius: 4,
backgroundColor: "rgba(255, 255, 255, 0.1)"
}}
/>
@@ -1024,43 +1048,43 @@ const Apps2 = (props) => {
}, []);
// Fetch apps based on the current tab : 0 -> org_apps, 1 -> my_apps, 2 -> all_apps
useEffect(() => {
const fetchApps = async () => {
const baseUrl = globalUrl;
let url;
setIsLoading(true);
const userId = userdata?.id;
if (currTab === 1 && userId) {
url = `${baseUrl}/api/v1/users/${userId}/apps`;
const fetchApps = async () => {
const baseUrl = globalUrl;
let url;
setIsLoading(true);
const userId = userdata?.id;
if (currTab === 1 && userId) {
url = `${baseUrl}/api/v1/users/${userId}/apps`;
} else if (currTab === 0) {
url = `${baseUrl}/api/v1/apps`;
}
try {
const response = await fetch(url, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
});
const data = await response.json();
if (currTab === 1) {
setAppsToShow(data);
setUserApps(data);
} else if (currTab === 0) {
url = `${baseUrl}/api/v1/apps`;
setAppsToShow(data);
setOrgApps(data);
// For testing the empty state
// setAppsToShow([]);
// setOrgApps([]);
}
try {
const response = await fetch(url, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
});
const data = await response.json();
if (currTab === 1) {
setAppsToShow(data);
setUserApps(data);
} else if (currTab === 0) {
setAppsToShow(data);
setOrgApps(data);
// For testing the empty state
// setAppsToShow([]);
// setOrgApps([]);
}
setIsLoading(false);
} catch (err) {
console.error("Error fetching apps:", err);
setIsLoading(false);
}
};
setIsLoading(false);
} catch (err) {
console.error("Error fetching apps:", err);
setIsLoading(false);
}
};
useEffect(() => {
// Only fetch if we have required data
if (globalUrl && (currTab === 0 || (currTab === 1 && userdata?.id))) {
@@ -1164,15 +1188,16 @@ const Apps2 = (props) => {
return response.json();
})
.then((responseJson) => {
//responseJson = sortByKey(responseJson, "large_image")
//responseJson = sortByKey(responseJson, "is_valid")
//setFilteredApps(responseJson.filter(app => !internalIds.includes(app.name) && !(!app.activated && app.generated)))
console.log("responseJson: from getApps ", responseJson)
var privateapps = [];
var valid = [];
var invalid = [];
for (var key in responseJson) {
const app = responseJson[key];
if (app.categories !== undefined && app.categories !== null && app?.categories.includes("Eradication")) {
app.categories = ["EDR"]
}
if (app.is_valid && !(!app.activated && app.generated)) {
privateapps.push(app);
} else if (
@@ -1185,21 +1210,13 @@ const Apps2 = (props) => {
}
}
//console.log(privateapps)
//console.log(valid)
//console.log(invalid)
//console.log(privateapps)
//privateapps.reverse()
privateapps.push(...valid);
privateapps.push(...invalid);
console.log("privateapps: setting apps ", privateapps)
setAppsToShow(privateapps);
setOrgApps(privateapps);
setApps(privateapps);
// setCursearch("");
//handleSearchChange(event.target.value)
//setCursearch(event.target.value)
// setFilteredApps(privateapps);
if (privateapps.length > 0) {
if (selectedApp.id === undefined || selectedApp.id === null) {
@@ -1707,8 +1724,24 @@ const Apps2 = (props) => {
setOpenModal(false)
}
const tabStyle = {
textTransform: 'none',
marginRight: 20,
fontFamily: theme?.typography?.fontFamily,
fontSize: 16,
borderBottom: "5px solid transparent",
minHeight: "48px",
padding: "12px 16px",
}
const tabActive = {
borderBottom: "5px solid #FF8544",
borderRadius: "2px",
color: "#FF8544"
}
return (
<div style={{ paddingTop: 70, paddingLeft: leftSideBarOpenByClick ? 200 : 0, transition: "padding-left 0.3s ease", backgroundColor: "#1A1A1A", fontFamily: theme?.typography?.fontFamily, zoom: 0.8, }}>
<div style={{ paddingTop: 70, paddingLeft: leftSideBarOpenByClick ? 200 : 0, transition: "padding-left 0.3s ease", backgroundColor: "#1A1A1A", fontFamily: theme?.typography?.fontFamily, zoom: 0.7, }}>
<InstantSearch searchClient={searchClient} indexName="appsearch">
<AppModal
open={openModal}
@@ -1728,7 +1761,7 @@ const Apps2 = (props) => {
<div style={boxStyle}>
<div style={{ display: "flex", flexDirection: "row", width: "100%", justifyContent: "space-between" }}>
<Typography variant="h4" style={{ marginBottom: 20, paddingLeft: 15, textTransform: 'none', fontFamily: theme?.typography?.fontFamily }}>
Apps
{currTab === 0 ? "Org" : currTab === 1 ? "Your" : "Discover"} Apps
</Typography>
{isCloud ? null : (
<span style={{ display: "flex", gap: 15 }}>
@@ -1755,7 +1788,7 @@ const Apps2 = (props) => {
height: 45,
minWidth: 45,
backgroundColor: "#2F2F2F",
borderRadius: 8,
borderRadius: 4,
padding: "8px 16px",
}}
disabled={isLoading}
@@ -1795,7 +1828,7 @@ const Apps2 = (props) => {
height: 45,
minWidth: 45,
backgroundColor: "#2F2F2F",
borderRadius: 8,
borderRadius: 4,
padding: "8px 16px",
}}
disabled={isLoading}
@@ -1820,12 +1853,35 @@ const Apps2 = (props) => {
<Tabs
value={currTab}
onChange={(event, newTab) => handleTabChange(event, newTab)}
TabIndicatorProps={{ style: { height: '3px', borderRadius: 10, backgroundColor: "#FF8544" } }}
style={{ fontFamily: theme?.typography?.fontFamily }}
style={{
fontFamily: theme?.typography?.fontFamily,
fontSize: 16,
marginBottom: "-2px"
}}
TabIndicatorProps={{ style: { display: 'none' } }}
>
<Tab label="Organization Apps" style={{ textTransform: 'none', marginRight: 20, fontFamily: theme?.typography?.fontFamily }} />
<Tab label="My Apps" style={{ textTransform: 'none', marginRight: 20, fontFamily: theme?.typography?.fontFamily }} />
<Tab label="Discover Apps" style={{ textTransform: 'none', fontFamily: theme?.typography?.fontFamily }} />
<Tab
label="Organization Apps"
style={{
...tabStyle,
...(currTab === 0 ? tabActive : {})
}}
/>
<Tab
label="My Apps"
style={{
...tabStyle,
...(currTab === 1 ? tabActive : {})
}}
/>
<Tab
label="Discover Apps"
style={{
...tabStyle,
marginRight: 0,
...(currTab === 2 ? tabActive : {})
}}
/>
</Tabs>
</div>
<div style={{ display: "flex", justifyContent: "space-between", gap: 10, marginBottom: 20, height: 45, paddingRight: 25 }}>
@@ -1850,12 +1906,12 @@ const Apps2 = (props) => {
limit={5}
InputProps={{
style: {
borderRadius: 8,
borderRadius: 4,
height: 45
},
endAdornment: (
<InputAdornment position="end">
{searchQuery.length === 0 ? <Search /> : (
{searchQuery.length === 0 ? <SearchIcon /> : (
<ClearIcon
style={{ cursor: "pointer" }}
onClick={() => {
@@ -1892,7 +1948,7 @@ const Apps2 = (props) => {
displayEmpty
multiple
style={{
borderRadius: 8,
borderRadius: 4,
height: 45,
fontFamily: theme?.typography?.fontFamily
}}
@@ -1956,7 +2012,7 @@ const Apps2 = (props) => {
displayEmpty
multiple
style={{
borderRadius: 8,
borderRadius: 4,
height: 45,
fontFamily: theme?.typography?.fontFamily
}}
@@ -2014,7 +2070,7 @@ const Apps2 = (props) => {
style={{
height: "100%",
width: '100%',
borderRadius: '7px',
borderRadius: '4px',
textTransform: 'none',
backgroundColor: "#FF8544",
color: "#1A1A1A",
@@ -2022,7 +2078,7 @@ const Apps2 = (props) => {
fontSize: 16,
fontWeight: 500
}}
startIcon={<Add style={{ color: "#1A1A1A" }} />}
startIcon={<AddIcon style={{ color: "#1A1A1A" }} />}
>
Create an App
</Button>
@@ -2062,6 +2118,7 @@ const Apps2 = (props) => {
handleAppClick={handleAppClick}
leftSideBarOpenByClick={leftSideBarOpenByClick}
userdata={userdata}
fetchApps={fetchApps}
/>
))}
</div>
@@ -2106,6 +2163,7 @@ const Apps2 = (props) => {
{appsToShow.map((data, index) => (
<AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} currTab={currTab} userdata={userdata}
handleAppClick={handleAppClick} leftSideBarOpenByClick={leftSideBarOpenByClick}
fetchApps={fetchApps}
/>
))}
</div>
File diff suppressed because it is too large Load Diff