Synced files across admin systems

This commit is contained in:
Frikky
2024-12-13 00:10:38 +01:00
parent e8e168ccfe
commit 75e99e2232
14 changed files with 1620 additions and 829 deletions
+42 -22
View File
@@ -57,7 +57,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
: hover : hover
? "" ? ""
: "1px solid rgba(255,255,255,0.3)", : "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', 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 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 // Common dialog styles
const dialogStyle = { const dialogStyle = {
@@ -400,7 +400,13 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
Create New App Create New App
</Typography> </Typography>
<IconButton <IconButton
onClick={onClose} onClick={() => {
setOpenApi("")
setOpenApiError("")
setAppValidation("")
setValidation(false)
onClose()
}}
sx={{ sx={{
color: 'rgba(255, 255, 255, 0.7)', color: 'rgba(255, 255, 255, 0.7)',
'&:hover': { bgcolor: 'rgba(255, 255, 255, 0.1)' } '&: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 Create New App from Open API or Swagger
</Typography> </Typography>
<IconButton <IconButton
onClick={() => setOpenApiModal(false)} onClick={() => {
setOpenApiModal(false)
setGenerateAppModal(false)
setOpenApi("")
setOpenApiError("")
setAppValidation("")
setValidation(false)
}}
sx={{ sx={{
color: 'rgba(255,255,255,0.7)', color: 'rgba(255,255,255,0.7)',
'&:hover': { bgcolor: 'rgba(255,255,255,0.1)' } '&:hover': { bgcolor: 'rgba(255,255,255,0.1)' }
@@ -487,14 +500,16 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
</IconButton> </IconButton>
</DialogTitle> </DialogTitle>
<DialogContent sx={{ px: 4, py: 3 }}> <DialogContent sx={{ px: 4, py: 3 }}>
<div style={{ display: "flex", fontSize: '14px', gap: '5px', alignItems: 'center', marginBottom: '10px', fontFamily: theme?.typography?.fontFamily }}> <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: '14px' }}> <Typography sx={{ color: 'rgba(255,255,255,0.85)', fontSize: '16px' }}>
Paste in the URI for the OpenAPI or find out Paste in the URI for the OpenAPI or find out
</Typography> </Typography>
<Link style={{ <Link style={{
color: '#ff8544', color: '#ff8544',
textDecoration: 'none', textDecoration: 'none',
textDecoration: 'underline', textDecoration: 'underline',
fontSize: '16px',
fontFamily: theme?.typography?.fontFamily
}}> }}>
How to find URI for openAPI? How to find URI for openAPI?
</Link> </Link>
@@ -506,12 +521,13 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
fullWidth fullWidth
variant="outlined" variant="outlined"
placeholder="Open API URI" placeholder="Open API URI"
style={{ fontFamily: theme?.typography?.fontFamily, fontSize: '16px' }}
sx={{ sx={{
'& .MuiOutlinedInput-root': { '& .MuiOutlinedInput-root': {
height: '40px' height: '40px',
}, },
'& .MuiOutlinedInput-input::placeholder': { '& .MuiOutlinedInput-input::placeholder': {
fontSize: '14px' fontSize: '16px'
} }
}} }}
onChange={(e) => setOpenApi(e.target.value)} onChange={(e) => setOpenApi(e.target.value)}
@@ -526,7 +542,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
px: 3, px: 3,
textTransform: 'none', textTransform: 'none',
height: '40px', height: '40px',
fontSize: '14px', fontSize: '16px',
fontFamily: theme?.typography?.fontFamily, fontFamily: theme?.typography?.fontFamily,
cursor: 'pointer' cursor: 'pointer'
}} }}
@@ -562,7 +578,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
sx={{ sx={{
color: '#FF8544', color: '#FF8544',
borderColor: '#FF8544', borderColor: '#FF8544',
px: 3, px: 5,
py: 1, py: 1,
'&:hover': { '&:hover': {
borderColor: '#FF8544', borderColor: '#FF8544',
@@ -570,7 +586,8 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
}, },
textTransform: 'none', textTransform: 'none',
fontSize: '14px', fontSize: '14px',
fontFamily: theme?.typography?.fontFamily fontFamily: theme?.typography?.fontFamily,
height: '40px'
}} }}
> >
Upload Upload
@@ -605,7 +622,8 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
}, },
textTransform: 'none', textTransform: 'none',
py: 1.5, py: 1.5,
fontSize: '14px', mb: 1.5,
fontSize: '16px',
fontWeight: 500, fontWeight: 500,
width: '100%', width: '100%',
maxWidth: '300px', maxWidth: '300px',
@@ -648,7 +666,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
<Typography variant="h6" sx={{ <Typography variant="h6" sx={{
color: '#F1F1F1', color: '#F1F1F1',
fontWeight: 500, fontWeight: 500,
fontFamily: theme?.typography?.fontFamily fontFamily: theme?.typography?.fontFamily,
}}> }}>
Generate an app based on documentation (beta) Generate an app based on documentation (beta)
</Typography> </Typography>
@@ -656,6 +674,10 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
onClick={() => { onClick={() => {
setGenerateAppModal(false) setGenerateAppModal(false)
setOpenApiModal(false) setOpenApiModal(false)
setOpenApi("")
setOpenApiError("")
setAppValidation("")
setValidation(false)
}} }}
sx={{ sx={{
color: 'rgba(255,255,255,0.7)', 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 }}> <DialogContent sx={{ px: 4, py: 3, pt: 0 }}>
<Typography sx={{ <Typography sx={{
color: 'rgba(255,255,255,0.85)', color: 'rgba(255,255,255,0.85)',
mb: 3, mb: 2,
fontSize: '14px', fontSize: '14px',
mt:4, mt: 2,
fontFamily: theme?.typography?.fontFamily fontFamily: theme?.typography?.fontFamily
}}> }}>
Paste in a URL, and we will make it into an app for you. 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', color: 'white',
'& fieldset': { '& fieldset': {
borderWidth: '1px', borderWidth: '1px',
borderImage: 'linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) 1', borderImage: "linear-gradient(to right, #ff8544 0%, #ec517c 50%, #9c5af2 100%) 1",
borderImageSlice: 1,
}, },
'&:hover fieldset': { '&:hover fieldset': {
borderWidth: '1px', borderWidth: '1px',
borderImage: 'linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) 1', borderImage: "linear-gradient(to right, #ff8544 0%, #ec517c 50%, #9c5af2 100%) 1",
borderImageSlice: 1,
}, },
'&.Mui-focused fieldset': { '&.Mui-focused fieldset': {
borderWidth: '2px', borderWidth: '2px',
borderImage: 'linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet) 1', borderImage: "linear-gradient(to right, #ff8544 0%, #ec517c 50%, #9c5af2 100%) 1",
borderImageSlice: 1,
} }
}, },
'& .MuiOutlinedInput-input::placeholder': { '& .MuiOutlinedInput-input::placeholder': {
@@ -727,6 +746,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
</DialogContent> </DialogContent>
<DialogActions sx={{ <DialogActions sx={{
py: 2, py: 2,
pt: 1,
px: 3, px: 3,
gap: 2, gap: 2,
display: 'flex', display: 'flex',
@@ -736,7 +756,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
{circularLoader} {circularLoader}
{ {
!validation && !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. This may take multiple minutes based on the size of the documentation.
</Typography> </Typography>
} }
+18 -21
View File
@@ -433,7 +433,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
fontFamily: theme?.typography?.fontFamily 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())} About {app?.name.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase())}
</Typography> </Typography>
<IconButton <IconButton
@@ -464,31 +464,28 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.2)" 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={{ <div style={{
display: "flex", display: "flex",
flexDirection: "row", flexDirection: "row",
alignItems: "center",
}}> }}>
<Typography variant="h5" component="div" sx={{ fontWeight: 600 }}> <Typography variant="h5" component="div" sx={{ fontWeight: 600 }}>
{newAppname} {newAppname}
</Typography> </Typography>
{ <Link
isCloud && ( to={"/apps/" + (app?.id || app?.objectID)}
<Link style={{ textDecoration: "none", color: "#f85a3e", marginTop: "-2px" }}
to={"/apps/" + (app?.id || app?.objectID)} >
style={{ textDecoration: "none", color: "#f85a3e", marginTop: "-2px" }} <IconButton
> style={{
<IconButton color: "#f85a3e",
style={{ fontSize: 16,
color: "#f85a3e", }}
fontSize: 20, >
}} <OpenInNewIcon />
> </IconButton>
<OpenInNewIcon /> </Link>
</IconButton>
</Link>
)
}
</div> </div>
<Typography <Typography
variant="body2" variant="body2"
@@ -547,7 +544,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
if (canEditApp) { if (canEditApp) {
const editUrl = "/apps/edit/" + (app?.id || app?.objectID); const editUrl = "/apps/edit/" + (app?.id || app?.objectID);
navigate(editUrl) navigate(editUrl)
}else{ } else {
const forkUrl = "/apps/new?id=" + (app?.id || app?.objectID); const forkUrl = "/apps/new?id=" + (app?.id || app?.objectID);
navigate(forkUrl) navigate(forkUrl)
} }
@@ -735,7 +732,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
bgcolor: '#FF8544', bgcolor: '#FF8544',
'&:hover': { bgcolor: '#FF8544' }, '&:hover': { bgcolor: '#FF8544' },
textTransform: 'none', textTransform: 'none',
borderRadius: 1, borderRadius: "4px",
py: 1, py: 1,
px: 7, px: 7,
fontSize: "14px", fontSize: "14px",
+6 -4
View File
@@ -466,14 +466,16 @@ const AppSelection = props => {
fontSize: 16, fontSize: 16,
color: "rgba(158, 158, 158, 1)", color: "rgba(158, 158, 158, 1)",
fontFamily: theme?.typography?.fontFamily, fontFamily: theme?.typography?.fontFamily,
lineHeight: "24px"
}} }}
> >
Your organization has no apps yet, select your starting apps here {`${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 or discover more apps using the`}
<span
onClick={() => { 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> </span>
</div> </div>
) )
+248 -124
View File
@@ -51,11 +51,13 @@ import BillingStats from "./BillingStats.jsx";
import { handlePayasyougo } from "../views/HandlePaymentNew.jsx" import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
import DeleteIcon from '@mui/icons-material/Delete'; import DeleteIcon from '@mui/icons-material/Delete';
import { Context } from "../context/ContextApi.jsx"; import { Context } from "../context/ContextApi.jsx";
import LicencePopup from "./LicencePopup.jsx";
const Billing = memo((props) => { 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(); //const alert = useAlert();
let navigate = useNavigate(); let navigate = useNavigate();
const [isLoggedIn, setIsLoggedIn] = useState(false)
const [selectedDealModalOpen, setSelectedDealModalOpen] = React.useState(false); const [selectedDealModalOpen, setSelectedDealModalOpen] = React.useState(false);
const [dealList, setDealList] = React.useState([]); const [dealList, setDealList] = React.useState([]);
const [dealName, setDealName] = React.useState(""); const [dealName, setDealName] = React.useState("");
@@ -73,14 +75,17 @@ const Billing = memo((props) => {
const [currentAppRunsInNumber, setCurrentAppRunsInNumber] = useState(0); 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 [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 [currentIndex, setCurrentIndex] = useState(0);
const [deleteAlertIndex, setDeleteAlertIndex] = useState(-1);
const [deleteAlertVerification, setDeleteAlertVerification] = useState(false); const [deleteAlertVerification, setDeleteAlertVerification] = useState(false);
useEffect(() => { useEffect(() => {
if (userdata.app_execution_limit !== undefined && userdata.app_execution_usage !== undefined) { if (userdata.app_execution_limit !== undefined && userdata.app_execution_usage !== undefined) {
const percentage = (userdata.app_execution_usage / userdata.app_execution_limit) * 100; const percentage = (userdata.app_execution_usage / userdata.app_execution_limit) * 100;
setCurrentAppRunsInPercentage(Math.round(percentage)); setCurrentAppRunsInPercentage(Math.round(percentage));
setCurrentAppRunsInNumber(userdata.app_execution_limit - userdata.app_execution_usage); setCurrentAppRunsInNumber(userdata.app_execution_limit - userdata.app_execution_usage);
} }
if (userdata?.id?.length > 0 && isLoggedIn === false){
setIsLoggedIn(true)
}
}, [userdata]); }, [userdata]);
const [BillingEmail, setBillingEmail] = useState(selectedOrganization?.Billing?.Email); const [BillingEmail, setBillingEmail] = useState(selectedOrganization?.Billing?.Email);
@@ -182,7 +187,8 @@ const Billing = memo((props) => {
const isCloud = const isCloud =
window.location.host === "localhost:3002" || window.location.host === "localhost:3002" ||
window.location.host === "shuffler.io"; window.location.host === "shuffler.io" ||
window.location.host === "sandbox.shuffler.io";
billingInfo.subscription = { billingInfo.subscription = {
"active": true, "active": true,
@@ -419,8 +425,16 @@ const Billing = memo((props) => {
const data = { const data = {
org_id: orgId, org_id: orgId,
email: newBillingEmail, 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: { billing: {
email: newBillingEmail, email: newBillingEmail,
AlertThreshold: selectedOrganization?.Billing?.AlertThreshold,
Consultation: selectedOrganization?.Billing?.Consultation,
}, },
}; };
@@ -747,13 +761,21 @@ const Billing = memo((props) => {
open={openChangeEmailBox} open={openChangeEmailBox}
onClose={handleCloseChangeEmailBox} onClose={handleCloseChangeEmailBox}
PaperProps={{ PaperProps={{
style: { sx: {
padding: '20px', borderRadius: theme?.palette?.DialogStyle?.borderRadius,
borderRadius: '8px', border: theme?.palette?.DialogStyle?.border,
maxWidth: '500px', minWidth: '440px',
width: '100%' 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> <DialogTitle style={{ fontSize: '1.5rem', fontWeight: 'bold' }}>Change Billing Email</DialogTitle>
<DialogContent> <DialogContent>
@@ -810,7 +832,7 @@ const Billing = memo((props) => {
color="primary" color="primary"
style={{ style={{
marginTop: !userdata.has_card_available ? 20 : 10, marginTop: !userdata.has_card_available ? 20 : 10,
borderRadius: 8, borderRadius: 4,
height: 40, height: 40,
fontSize: 16, fontSize: 16,
color: userdata.has_card_available ? "#ff8544" : "#1a1a1a", color: userdata.has_card_available ? "#ff8544" : "#1a1a1a",
@@ -843,7 +865,7 @@ const Billing = memo((props) => {
color="primary" color="primary"
style={{ style={{
marginTop: 10, marginTop: 10,
borderRadius: 8, borderRadius: 4,
height: 40, height: 40,
fontSize: 16, fontSize: 16,
color: "#1a1a1a", color: "#1a1a1a",
@@ -933,11 +955,19 @@ const Billing = memo((props) => {
const url = `${globalUrl}/api/v1/orgs/${selectedOrganization.id}`; const url = `${globalUrl}/api/v1/orgs/${selectedOrganization.id}`;
const data = { const data = {
org_id: selectedOrganization.id, 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: { Billing: {
Consultation: { Consultation: {
hours: String(inputHour), hours: String(inputHour),
minutes: String(inputMinutes), minutes: String(inputMinutes),
}, },
AlertThreshold: selectedOrganization.Billing.AlertThreshold,
email: selectedOrganization.Billing.email,
} }
}; };
@@ -1030,9 +1060,9 @@ const Billing = memo((props) => {
<div style={{ <div style={{
padding: 20, padding: 20,
// maxWidth: 400, // maxWidth: 400,
width: 340, width: "100%",
height: 480, height: 480,
backgroundColor: hovered ? "#2b2b2b" : theme.palette.backgroundColor, backgroundColor: hovered ? "#2b2b2b" : "#1e1e1e",
borderRadius: theme.palette?.borderRadius * 2, borderRadius: theme.palette?.borderRadius * 2,
border: "1px solid rgba(255,255,255,0.3)", border: "1px solid rgba(255,255,255,0.3)",
marginRight: 10, marginRight: 10,
@@ -1123,7 +1153,7 @@ const Billing = memo((props) => {
color="primary" color="primary"
style={{ style={{
marginTop: userdata.support ? 0 : 10, marginTop: userdata.support ? 0 : 10,
borderRadius: 8, borderRadius: 4,
height: 40, height: 40,
fontSize: 16, fontSize: 16,
color: "#1A1A1A", color: "#1A1A1A",
@@ -1142,8 +1172,23 @@ const Billing = memo((props) => {
> >
Buy Buy
</Button> </Button>
<Dialog open={clickOnBuy} onClose={() => { setClickOnBuy(false) }} PaperProps={{style: {backgroundColor: "rgb(26, 26, 26)"}}}> <Dialog open={clickOnBuy} onClose={() => { setClickOnBuy(false) }} PaperProps={{
<Typography variant="body1" style={{ marginTop: 10, textAlign: 'center', padding: 20, fontSize: 18 }}> 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. 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> </Typography>
<DialogContent> <DialogContent>
@@ -1178,10 +1223,9 @@ const Billing = memo((props) => {
color="primary" color="primary"
style={{ style={{
marginTop: userdata.support ? 5 : 10, marginTop: userdata.support ? 5 : 10,
borderRadius: 8, borderRadius: 4,
height: 40, height: 40,
fontSize: 16, fontSize: 16,
color: "#ff8544",
textTransform: 'none', textTransform: 'none',
cursor: getProfessionalServices ? 'pointer' : 'not-allowed', cursor: getProfessionalServices ? 'pointer' : 'not-allowed',
opacity: getProfessionalServices ? 1 : 0.6, opacity: getProfessionalServices ? 1 : 0.6,
@@ -1202,13 +1246,23 @@ const Billing = memo((props) => {
fullWidth fullWidth
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }} style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}
PaperProps={{ PaperProps={{
style: { sx: {
width: 500, borderRadius: theme?.palette?.DialogStyle?.borderRadius,
margin: 0, 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 Upgrade Consultation Plan
</DialogTitle> </DialogTitle>
<DialogContent style={{ padding: '24px', }}> <DialogContent style={{ padding: '24px', }}>
@@ -1244,7 +1298,7 @@ const Billing = memo((props) => {
<Button <Button
variant="contained" variant="contained"
color="primary" 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} onClick={handleUpgradeConsultation}
> >
Submit Request for {consultationHours} hours Submit Request for {consultationHours} hours
@@ -1305,8 +1359,8 @@ const Billing = memo((props) => {
padding: 20, padding: 20,
height: 480, height: 480,
// maxWidth: 400, // maxWidth: 400,
width: 340, width: "100%",
backgroundColor: hovered ? "#2b2b2b" : theme.palette.backgroundColor, backgroundColor: hovered ? "#2b2b2b" : "#1e1e1e",
borderRadius: theme.palette?.borderRadius * 2, borderRadius: theme.palette?.borderRadius * 2,
border: "1px solid rgba(255,255,255,0.3)", border: "1px solid rgba(255,255,255,0.3)",
marginRight: 10, marginRight: 10,
@@ -1354,7 +1408,7 @@ const Billing = memo((props) => {
</li> </li>
</ul> </ul>
</div> </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 <Button
fullWidth fullWidth
disabled={false} disabled={false}
@@ -1362,12 +1416,13 @@ const Billing = memo((props) => {
color="primary" color="primary"
style={{ style={{
marginTop: 10, marginTop: 10,
borderRadius: 8, borderRadius: 4,
height: 40, height: 40,
fontSize: 16, fontSize: 16,
color: "#1A1A1A", color: "#1A1A1A",
textTransform: 'none', textTransform: 'none',
backgroundColor: "#FF8544" backgroundColor: "#FF8544",
width: "100%",
}} }}
onClick={() => { onClick={() => {
if (Cloud) { if (Cloud) {
@@ -1390,12 +1445,11 @@ const Billing = memo((props) => {
color="primary" color="primary"
style={{ style={{
marginTop: 10, marginTop: 10,
borderRadius: 8, borderRadius: 4,
height: 40, height: 40,
fontSize: 16, fontSize: 16,
textTransform: 'none', textTransform: 'none',
color: "#FF8544", width: "100%",
backgroundColor: "#1a1a1a",
}} }}
onClick={() => { onClick={() => {
if (Cloud) { if (Cloud) {
@@ -1417,14 +1471,23 @@ const Billing = memo((props) => {
fullWidth fullWidth
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }} style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}
PaperProps={{ PaperProps={{
style: { sx: {
width: 500, borderRadius: theme?.palette?.DialogStyle?.borderRadius,
margin: 0, border: theme?.palette?.DialogStyle?.border,
backgroundColor: "rgb(26, 26, 26)", 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 Private Training
</DialogTitle> </DialogTitle>
<DialogContent style={{ padding: '24px', }}> <DialogContent style={{ padding: '24px', }}>
@@ -1460,7 +1523,7 @@ const Billing = memo((props) => {
<Button <Button
variant="contained" variant="contained"
color="primary" 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} onClick={handlePrivateTraining}
> >
Submit Request Submit Request
@@ -1819,7 +1882,6 @@ const Billing = memo((props) => {
setCurrentIndex(findCurrentIndex ? newAlertThresholds.findIndex(threshold => threshold.Email_send === false) : - 1); setCurrentIndex(findCurrentIndex ? newAlertThresholds.findIndex(threshold => threshold.Email_send === false) : - 1);
toast.info("Alert Threshold deleted successfully. Don't forget to save your changes."); toast.info("Alert Threshold deleted successfully. Don't forget to save your changes.");
}; };
const HandleEditOrgForAlertThreshold = (orgId) => { const HandleEditOrgForAlertThreshold = (orgId) => {
// Use the `some` method to check for invalid counts // Use the `some` method to check for invalid counts
@@ -1840,6 +1902,12 @@ const Billing = memo((props) => {
const data = { const data = {
org_id: orgId, 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: { billing: {
email: BillingEmail, email: BillingEmail,
AlertThreshold: alertThresholds.map(threshold => ({ AlertThreshold: alertThresholds.map(threshold => ({
@@ -1847,6 +1915,7 @@ const Billing = memo((props) => {
percentage: parseInt(threshold.percentage, 10), percentage: parseInt(threshold.percentage, 10),
count: parseInt(threshold.count, 10), count: parseInt(threshold.count, 10),
})), })),
Consultation: selectedOrganization?.billing?.Consultation,
}, },
}; };
@@ -1901,12 +1970,12 @@ const Billing = memo((props) => {
Billing & Licensing Billing & Licensing
</Typography>} </Typography>}
{clickedFromOrgTab ? {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." "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." "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> : }</span> :
<Typography variant="body1" color="textSecondary" style={{ marginTop: 0, marginBottom: 10 }}> <Typography variant="body1" color="textSecondary" style={{ marginTop: 0, marginBottom: 10, fontSize: 16 }}>
{isCloud ? {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." "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 ? {userdata.support === true ?
<div style={{ marginBottom: 10, marginTop: clickedFromOrgTab ? 16 : null, color: clickedFromOrgTab ? "#F1F1F1" : null }}> <div style={{ marginBottom: 10, marginTop: clickedFromOrgTab ? 16 : null, color: clickedFromOrgTab ? "#F1F1F1" : null }}>
For sales: Create&nbsp; 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 EU contract
</a> </a>
&nbsp;or&nbsp; &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 NOT EU contract
</a> </a>
&nbsp; - &nbsp; &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 Google Drive Link
</a> </a>
&nbsp; - &nbsp; &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) Sales Process (old)
</a> </a>
</div> </div>
@@ -1944,22 +2013,24 @@ const Billing = memo((props) => {
</Typography> </Typography>
: null} : 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 : {isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? isChildOrg ? null :
<SubscriptionObject <LicencePopup
index={0} serverside={serverside}
globalUrl={globalUrl} removeCookie={removeCookie}
userdata={userdata} isLoaded={isLoaded}
serverside={serverside} isLoggedIn={isLoggedIn}
billingInfo={billingInfo} globalUrl={globalUrl}
stripeKey={stripeKey} selectedOrganization={selectedOrganization}
selectedOrganization={selectedOrganization} billingInfo={billingInfo}
subscription={billingInfo.subscription} isCloud={isCloud}
highlight={selectedOrganization.subscriptions === undefined || selectedOrganization.subscriptions === null || selectedOrganization.subscriptions.length === 0} userdata={userdata}
stripeKey={stripeKey}
{...props}
/> />
: !isCloud ? : !isCloud ?
<span style={{ display: "flex", }}> <span style={{ display: "flex", }}>
<SubscriptionObject {/* <SubscriptionObject
index={0} index={0}
globalUrl={globalUrl} globalUrl={globalUrl}
userdata={userdata} userdata={userdata}
@@ -1977,8 +2048,22 @@ const Billing = memo((props) => {
], ],
}} }}
highlight={true} highlight={true}
/> */}
<LicencePopup
{...props}
serverside={serverside}
removeCookie={removeCookie}
isLoaded={isLoaded}
isLoggedIn={isLoggedIn}
globalUrl={globalUrl}
selectedOrganization={selectedOrganization}
billingInfo={billingInfo}
isCloud={isCloud}
userdata={userdata}
stripeKey={stripeKey}
/> />
<SubscriptionObject
{/* <SubscriptionObject
index={1} index={1}
globalUrl={globalUrl} globalUrl={globalUrl}
userdata={userdata} userdata={userdata}
@@ -1996,7 +2081,7 @@ const Billing = memo((props) => {
], ],
}} }}
highlight={false} highlight={false}
/> /> */}
</span> </span>
: null} : null}
@@ -2255,14 +2340,14 @@ const Billing = memo((props) => {
</div> </div>
) : null*/} ) : null*/}
{!isChildOrg && isCloud && ( {!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" }}> <Typography style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}>
Professional Services Professional Services
</Typography> </Typography>
<Typography color="textSecondary" style={{fontSize: 16,}}> <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. 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> </Typography>
<div style={{ display: 'flex', flexDirection: 'row', marginTop: 5 }}> <div style={{ display: 'flex', flexDirection: 'row', marginTop: 5, }}>
{billingInfo.subscription !== undefined && billingInfo.subscription !== null ? ( {billingInfo.subscription !== undefined && billingInfo.subscription !== null ? (
isChildOrg ? null : ( isChildOrg ? null : (
<ConsultationManagement <ConsultationManagement
@@ -2276,7 +2361,7 @@ const Billing = memo((props) => {
</div> </div>
</div> </div>
)} )}
<div style={{ marginTop: isCloud && 40, marginLeft: 10 }}> <div style={{ marginTop: 40, marginLeft: 10 }}>
<Typography <Typography
style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }} style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}
> >
@@ -2323,43 +2408,51 @@ const Billing = memo((props) => {
<div style={{ marginTop: 15 }}> <div style={{ marginTop: 15 }}>
{alertThresholds.map((threshold, index) => ( {alertThresholds.map((threshold, index) => (
<div key={index} style={{ display: 'flex', alignItems: 'center' }}> <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 <TextField
style={{ style={{
marginTop: 10, marginTop: 10,
backgroundColor: "#212121", height: 50,
width: 250, backgroundColor: "#212121",
width: 250,
marginLeft: 15,
}} }}
InputProps={{ InputProps={{
style: { style: {
height: 50, height: 50,
color: 'white', color: 'white',
}, },
endAdornment: '%',
}} }}
color="primary" InputLabelProps={{
fullWidth shrink: undefined,
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',
},
}} }}
color="primary" color="primary"
fullWidth fullWidth
@@ -2370,34 +2463,67 @@ const Billing = memo((props) => {
margin="normal" margin="normal"
variant="outlined" 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> <span
{ style={{
alertThresholds.length > 1 && marginLeft: alertThresholds[index].Email_send === true ? 10 : 35,
( color: 'green',
<Button }}
disableRipple >
disableElevation {alertThresholds[index].Email_send === true && (
sx={{ <Tooltip title="We have already sent alert for this threshold.">
padding: 0, <CheckCircle />
'&:hover': { </Tooltip>
backgroundColor: 'transparent', )}
}, </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>
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>
))} ))}
</div> </div>
</div> </div>
@@ -2449,10 +2575,8 @@ const PaddingWrapper = memo(({ clickedFromOrgTab, children }) => {
: "auto", : "auto",
padding: "27px 10px 19px 27px", padding: "27px 10px 19px 27px",
backgroundColor: '#212121', backgroundColor: '#212121',
borderRadius: '16px',
height: '100%', height: '100%',
boxSizing: 'border-box', boxSizing: 'border-box',
borderLeft: '1px solid #494949',
overflow: 'hidden', overflow: 'hidden',
maxHeight: "1700px", overflowY: "auto",scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' maxHeight: "1700px", overflowY: "auto",scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'
}), [clickedFromOrgTab]); }), [clickedFromOrgTab]);
+123 -29
View File
@@ -648,12 +648,13 @@ const AppStats = (defaultprops) => {
All shown statistics are gathered from <a All shown statistics are gathered from <a
href={`${globalUrl}/api/v1/orgs/${selectedOrganization.id}/stats`} href={`${globalUrl}/api/v1/orgs/${selectedOrganization.id}/stats`}
target="_blank" target="_blank"
style={{ textDecoration: "none", color: "#f85a3e",}} style={{ textDecoration: "none", color: "#FF8444",}}
>Your Organisation Statistics. </a> >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> 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> </Typography>
<div style={{display: "flex", textAlign: "center",}}> <div style={{display: "flex", flexDirection: "column", textAlign: "center",}}>
<div style={{flexDirection: "row", }}>
{filteredStatistics !== undefined ? {filteredStatistics !== undefined ?
<div style={{flex: 1, display: "flex", textAlign: "center",}}> <div style={{flex: 1, display: "flex", textAlign: "center",}}>
<Tooltip title={ <Tooltip title={
@@ -726,40 +727,135 @@ const AppStats = (defaultprops) => {
</Tooltip> </Tooltip>
</div> </div>
: null} : null}
</div>
{clickedFromOrgTab? ( {clickedFromOrgTab? (
<LocalizationProvider dateAdapter={AdapterDayjs} style={{ flex: 1 }}> <LocalizationProvider dateAdapter={AdapterDayjs} style={{ flex: 1 }}>
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}> <div style={{ display: "flex", flexDirection: "row", width: "100%", gap: "10px", justifyContent: 'center', alignItems: 'center', paddingTop: 10 }}>
<div style={{ flex: 1, maxWidth: "200px", }}> <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 <DateTimePicker
sx={{ slotProps={{
marginTop: 1, textField: {
marginLeft: 1, sx: {
}} "& .MuiOutlinedInput-root": {
ampm={false} "& fieldset": {
label="Search from" borderColor: "#494949 !important",
format="YYYY-MM-DD HH:mm:ss" borderWidth: "1px !important",
value={startTime} },
onChange={handleStartTimeChange} "&:hover fieldset": {
renderInput={(params) => <TextField {...params} />} 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>
<div style={{ flex: 1, maxWidth: "200px",}}> <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 <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, marginTop: 1,
marginLeft: 1, "& .MuiInputBase-root": {
}} height: "35px",
ampm={false} minHeight: "35px",
label="Search until" },
format="YYYY-MM-DD HH:mm:ss" "& .MuiInputBase-input": {
value={endTime} height: "35px",
onChange={handleEndTimeChange} padding: "0 14px",
renderInput={(params) => <TextField {...params} />} boxSizing: "border-box",
color: "#c8c8c8",
fontSize: 16,
}
}}
ampm={false}
format="YYYY-MM-DD HH:mm:ss"
value={endTime}
onChange={handleEndTimeChange}
/> />
</div> </div>
</div> </div>
</LocalizationProvider> </LocalizationProvider>
):( ):(
<LocalizationProvider dateAdapter={AdapterDayjs} style={{flex: 1, }}> <LocalizationProvider dateAdapter={AdapterDayjs} style={{flex: 1, }}>
<div style={{display: "flex", flexDirection: "column", }}> <div style={{display: "flex", flexDirection: "column", }}>
@@ -794,8 +890,6 @@ const AppStats = (defaultprops) => {
</div> </div>
</LocalizationProvider> </LocalizationProvider>
)} )}
</div> </div>
{appRuns === undefined ? {appRuns === undefined ?
+11 -10
View File
@@ -412,7 +412,7 @@ const CacheView = memo((props) => {
</span> </span>
</div> </div>
<Button <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" variant="contained"
color="primary" color="primary"
onClick={() =>{ onClick={() =>{
@@ -425,7 +425,7 @@ const CacheView = memo((props) => {
Add Cache Add Cache
</Button> </Button>
<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" variant="contained"
color="primary" color="primary"
onClick={() => listOrgCache(orgId)} onClick={() => listOrgCache(orgId)}
@@ -440,7 +440,7 @@ const CacheView = memo((props) => {
/>} />}
<div <div
style={{ style={{
borderRadius: 8, borderRadius: 4,
marginTop: 24, marginTop: 24,
border: "1px solid #494949", border: "1px solid #494949",
width: "100%", width: "100%",
@@ -450,7 +450,7 @@ const CacheView = memo((props) => {
> >
<List <List
style={{ style={{
borderRadius: 8, borderRadius: 4,
paddingBottom: 0, paddingBottom: 0,
tableLayout: "auto", tableLayout: "auto",
display: "table", display: "table",
@@ -465,7 +465,7 @@ const CacheView = memo((props) => {
primary={header} primary={header}
style={{ style={{
display: "table-cell", display: "table-cell",
padding: "0px 8px 8px 8px", padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px",
whiteSpace: "nowrap", whiteSpace: "nowrap",
overflow: "hidden", overflow: "hidden",
textOverflow: "ellipsis", textOverflow: "ellipsis",
@@ -518,13 +518,13 @@ const CacheView = memo((props) => {
const validate = validateJson(data.value); const validate = validateJson(data.value);
return ( 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 <ListItemText
style={{ style={{
display: "table-cell", display: "table-cell",
overflow: "hidden", overflow: "hidden",
padding: 8,
verticalAlign: "middle", verticalAlign: "middle",
padding: "8px 8px 8px 15px"
}} }}
primary={data.key} primary={data.key}
/> />
@@ -533,9 +533,8 @@ const CacheView = memo((props) => {
display: "table-cell", display: "table-cell",
overflowY: "auto", overflowY: "auto",
overflowX: "auto", overflowX: "auto",
border: "1px solid rgba(255,255,255,0.7)", borderRadius: 4,
borderRadius: 6, padding: "15px 5px",
backgroundColor: "#151515",
maxHeight: 300, maxHeight: 300,
verticalAlign: "middle", verticalAlign: "middle",
}} }}
@@ -547,6 +546,8 @@ const CacheView = memo((props) => {
padding: 5, padding: 5,
maxHeight: 300, maxHeight: 300,
overflowY: "auto", overflowY: "auto",
backgroundColor: "#151515",
border: "1px solid rgba(255,255,255,0.7)",
}} }}
collapsed={true} collapsed={true}
enableClipboard={(copy) => { enableClipboard={(copy) => {
+37 -23
View File
@@ -690,7 +690,7 @@ const Files = memo((props) => {
onClick={() => { onClick={() => {
upload.click(); 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 Upload files
</Button> </Button>
@@ -711,7 +711,7 @@ const Files = memo((props) => {
}} }}
/> />
<Button <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" variant="contained"
color="primary" color="primary"
onClick={() => getFiles(selectedCategory)} onClick={() => getFiles(selectedCategory)}
@@ -788,7 +788,7 @@ const Files = memo((props) => {
: :
<Tooltip title={"Add new file category"} style={{}} aria-label={""}> <Tooltip title={"Add new file category"} style={{}} aria-label={""}>
<Button <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" color="primary"
onClick={() => { onClick={() => {
setRenderTextBox(true); setRenderTextBox(true);
@@ -838,7 +838,7 @@ const Files = memo((props) => {
/>} />}
<div <div
style={{ style={{
borderRadius: 8, borderRadius: 4,
marginTop: 24, marginTop: 24,
border: "1px solid #494949", border: "1px solid #494949",
width: "100%", width: "100%",
@@ -862,7 +862,7 @@ const Files = memo((props) => {
primary={header} primary={header}
style={{ style={{
display: "table-cell", display: "table-cell",
padding: "0px 8px 8px 8px", padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px",
whiteSpace: "nowrap", whiteSpace: "nowrap",
textOverflow: "ellipsis", textOverflow: "ellipsis",
borderBottom: "1px solid #494949", borderBottom: "1px solid #494949",
@@ -870,7 +870,7 @@ const Files = memo((props) => {
}} }}
primaryTypographyProps={{ primaryTypographyProps={{
style: { style: {
paddingLeft: index === 3 ? 80 : 10, paddingLeft: 10,
} }
}} }}
/> />
@@ -956,15 +956,13 @@ const Files = memo((props) => {
<ListItemText <ListItemText
primaryTypographyProps={{ primaryTypographyProps={{
style: { style: {
display: 'table-cell',
maxWidth: "170px", maxWidth: "170px",
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
textOverflow: 'ellipsis', textOverflow: 'ellipsis',
overflow: 'hidden', overflow: 'hidden',
padding: 8 padding: "8px 8px 8px 20px"
}, }
}} }}
primary={file.filename} primary={file.filename}
/> />
<ListItemText <ListItemText
@@ -1005,6 +1003,7 @@ const Files = memo((props) => {
> >
<OpenInNewIcon <OpenInNewIcon
style={{ style={{
width: 24, height: 24,
color: color:
file.workflow_id !== "global" file.workflow_id !== "global"
? "#FF8444" ? "#FF8444"
@@ -1044,7 +1043,7 @@ const Files = memo((props) => {
style={{ style={{
display: 'table-cell', display: 'table-cell',
overflow: "hidden", overflow: "hidden",
textAlign:isSelectedFiles?"left":null, textAlign:isSelectedFiles?"center":null,
color: file.status === "active" ? "#2BC07E" : "#FD4C62" color: file.status === "active" ? "#2BC07E" : "#FD4C62"
}} }}
/> />
@@ -1074,7 +1073,7 @@ const Files = memo((props) => {
}} }}
> >
<img src="/icons/editIcon.svg" alt="edit icon" <img src="/icons/editIcon.svg" alt="edit icon"
style={{color: iseditable ? "white" : "grey",}} style={{color: iseditable ? "white" : "grey", width: 24, height: 24}}
/> />
</IconButton> </IconButton>
</span> </span>
@@ -1120,6 +1119,7 @@ const Files = memo((props) => {
> >
<img src="/icons/downloadIcon.svg" alt="download icon" <img src="/icons/downloadIcon.svg" alt="download icon"
style={{ style={{
width: 24, height: 24,
color: color:
file.status === "active" file.status === "active"
? "white" ? "white"
@@ -1144,7 +1144,7 @@ const Files = memo((props) => {
toast(file.id + " copied to clipboard"); 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> </IconButton>
</Tooltip> </Tooltip>
<Tooltip <Tooltip
@@ -1155,21 +1155,35 @@ const Files = memo((props) => {
<span> <span>
<IconButton <IconButton
disabled={file.status !== "active"} disabled={file.status !== "active"}
style = {{padding: "6px"}} style={{ padding: "6px" }}
onClick={() => { onClick={() => {
deleteFile(file) deleteFile(file);
}} }}
> >
<img src="/icons/deleteIcon.svg" alt="delete icon" <svg
style={{ width="24"
color: height="24"
file.status === "active" viewBox="0 0 24 24"
? "white" xmlns="http://www.w3.org/2000/svg"
: "grey", 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> </IconButton>
</span> </span>
</Tooltip> </Tooltip>
</span> </span>
style={{ style={{
+42 -27
View File
@@ -229,7 +229,7 @@ useEffect(() => {
setOpenautomateTab(false); setOpenautomateTab(false);
setOpenSecurityTab(true); setOpenSecurityTab(true);
setCurrentOpenTab("security"); setCurrentOpenTab("security");
} else if ((lastTabOpenByUser === "usecases" && currentPath.includes("/usecases2")) || currentPath.includes("/usecases2")) { } else if ((lastTabOpenByUser === "usecases" && currentPath.includes("/usecases")) || currentPath.includes("/usecases")) {
setOpenautomateTab(true); setOpenautomateTab(true);
setOpenSecurityTab(false); setOpenSecurityTab(false);
setCurrentOpenTab("usecases"); setCurrentOpenTab("usecases");
@@ -466,6 +466,7 @@ useEffect(() => {
onClick={(event) => { onClick={(event) => {
handleClose(); handleClose();
}} }}
style={{fontSize: 18}}
> >
<BusinessIcon style={{ marginRight: 5 }} /> Organization <BusinessIcon style={{ marginRight: 5 }} /> Organization
</MenuItem> </MenuItem>
@@ -475,6 +476,7 @@ useEffect(() => {
onClick={(event) => { onClick={(event) => {
handleClose(); handleClose();
}} }}
style={{fontSize: 18}}
> >
<SettingsIcon style={{ marginRight: 5 }} /> Account <SettingsIcon style={{ marginRight: 5 }} /> Account
</MenuItem> </MenuItem>
@@ -486,6 +488,7 @@ useEffect(() => {
onClick={(event) => { onClick={(event) => {
handleClose(); handleClose();
}} }}
style={{fontSize: 18}}
> >
<NotificationsIcon style={{ marginRight: 5 }} /> Notifications ({ <NotificationsIcon style={{ marginRight: 5 }} /> Notifications ({
notifications === undefined || notifications === null ? 0 : notifications === undefined || notifications === null ? 0 :
@@ -498,6 +501,7 @@ useEffect(() => {
onClick={(event) => { onClick={(event) => {
handleClose(); handleClose();
}} }}
style={{fontSize: 18}}
> >
<LightbulbIcon style={{ marginRight: 5 }} /> Use Cases <LightbulbIcon style={{ marginRight: 5 }} /> Use Cases
</MenuItem> </MenuItem>
@@ -510,23 +514,25 @@ useEffect(() => {
onClick={(event) => { onClick={(event) => {
handleClose(); handleClose();
}} }}
style={{fontSize: 18}}
> >
<HelpOutlineIcon style={{ marginRight: 5 }} /> About <HelpOutlineIcon style={{ marginRight: 5 }} /> About
</MenuItem> </MenuItem>
</Link> </Link>
<MenuItem <MenuItem
style={{ color: "white" }} style={{ color: "white", fontSize: 18 }}
onClick={(event) => { onClick={(event) => {
handleClickLogout(); handleClickLogout();
event.preventDefault(); event.preventDefault();
handleClose(); handleClose();
}} }}
> >
<MeetingRoomIcon style={{ marginRight: 5 }} /> &nbsp;Logout <MeetingRoomIcon style={{ marginRight: 5 }} /> &nbsp;Logout
</MenuItem> </MenuItem>
<Divider style={{ marginBottom: 10, }} /> <Divider style={{ marginBottom: 10, }} />
<Typography variant="body2" color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, }}> <Typography color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, fontSize: 18 }}>
Version: 2.0.0-beta Version: 2.0.0-beta
</Typography> </Typography>
</Menu> </Menu>
@@ -717,6 +723,7 @@ useEffect(() => {
width: expandLeftNav ? "100%" : 30, width: expandLeftNav ? "100%" : 30,
padding: 0, padding: 0,
}, },
fontSize: 18
}; };
const modalView = ( const modalView = (
@@ -936,6 +943,7 @@ useEffect(() => {
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
padding: expandLeftNav ? "0 16px" : "0px 8px", padding: expandLeftNav ? "0 16px" : "0px 8px",
gap: 1.2,
}} }}
> >
<Box sx={{ display: "flex", flexDirection: "row", marginTop: 2.5, width: expandLeftNav ? "100%" : 48, padding: "0px", }}> <Box sx={{ display: "flex", flexDirection: "row", marginTop: 2.5, width: expandLeftNav ? "100%" : 48, padding: "0px", }}>
@@ -950,18 +958,18 @@ useEffect(() => {
variant="text" variant="text"
style={{ style={{
...ButtonStyle, ...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)=>{ onMouseOver={(event)=>{
event.currentTarget.style.backgroundColor = "#2f2f2f"; event.currentTarget.style.backgroundColor = "#2f2f2f";
}} }}
onMouseOut={(event)=>{ 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 <img
src={detectionIcon} src={detectionIcon}
style={{ width: 16, height: 16, marginRight: expandLeftNav ? 10 : 0 }} style={{ width: 18, height: 18, marginRight: expandLeftNav ? 10 : 0 }}
alt="Automate Icon" alt="Automate Icon"
/> />
<span <span
@@ -1020,7 +1028,7 @@ useEffect(() => {
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
paddingLeft: 16, paddingLeft: 16,
gap: 4, gap: 10,
}} }}
> >
<Link to="/usecases" style={hrefStyle}> <Link to="/usecases" style={hrefStyle}>
@@ -1032,8 +1040,9 @@ useEffect(() => {
style={{ style={{
width: "100%", width: "100%",
height: 35, height: 35,
color: "#C8C8C8", color: currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases") ? "#FFFFFF" : "#C8C8C8",
justifyContent: "flex-start", justifyContent: "flex-start",
fontSize: 18,
textTransform: "none", textTransform: "none",
backgroundColor: currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases")? "#2f2f2f": "transparent", backgroundColor: currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases")? "#2f2f2f": "transparent",
marginLeft: 16 marginLeft: 16
@@ -1046,13 +1055,13 @@ useEffect(() => {
}} }}
disableRipple={expandLeftNav ? false : true} 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 <span
style={{ style={{
display: expandLeftNav ? "inline" : "none", display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0, opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease", transition: "opacity 0.3s ease",
color: currentOpenTab === "usecases" && currentPath.includes("/usecases3") ? "#F1F1F1" : "#C8C8C8", color: currentOpenTab === "usecases" && currentPath.includes("/usecases") ? "#FFFFFF" : "#C8C8C8",
}} }}
> >
Usecases Usecases
@@ -1068,11 +1077,12 @@ useEffect(() => {
style={{ style={{
width: "100%", width: "100%",
height: 35, height: 35,
color: "#C8C8C8", color: currentOpenTab === "workflows" && currentPath === "/workflows" ? "#FFFFFF" : "#C8C8C8",
justifyContent: "flex-start", justifyContent: "flex-start",
textTransform: "none", textTransform: "none",
backgroundColor: currentOpenTab === "workflows" && currentPath === "/workflows" && expandLeftNav? "#2f2f2f": "transparent", backgroundColor: currentOpenTab === "workflows" && currentPath === "/workflows" && expandLeftNav? "#2f2f2f": "transparent",
marginLeft: 16 marginLeft: 16,
fontSize: 18
}} }}
disableRipple={expandLeftNav ? false : true} disableRipple={expandLeftNav ? false : true}
onMouseOver={(event)=>{ onMouseOver={(event)=>{
@@ -1082,13 +1092,13 @@ useEffect(() => {
event.currentTarget.style.backgroundColor = currentOpenTab === "workflows" && currentPath === "/workflows" && expandLeftNav? "#2f2f2f": "transparent"; 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 <span
style={{ style={{
display: expandLeftNav ? "inline" : "none", display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0, opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease", transition: "opacity 0.3s ease",
color: currentOpenTab === "workflows" && currentPath === "/workflows" ? "#F1F1F1" : "#C8C8C8", color: currentOpenTab === "workflows" && currentPath === "/workflows" ? "#FFFFFF" : "#C8C8C8",
}} }}
> >
Workflows Workflows
@@ -1104,11 +1114,12 @@ useEffect(() => {
style={{ style={{
width: "100%", width: "100%",
height: 35, height: 35,
color: "#C8C8C8", color: currentOpenTab === "apps" && currentPath.includes("/apps") ? "#FFFFFF" : "#C8C8C8",
justifyContent: "flex-start", justifyContent: "flex-start",
textTransform: "none", textTransform: "none",
backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps2") ? "#2f2f2f": "transparent", backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps2") ? "#2f2f2f": "transparent",
marginLeft: 16 marginLeft: 16,
fontSize: 18
}} }}
onMouseOver={(event)=>{ onMouseOver={(event)=>{
event.currentTarget.style.backgroundColor = "#2f2f2f"; event.currentTarget.style.backgroundColor = "#2f2f2f";
@@ -1118,13 +1129,13 @@ useEffect(() => {
}} }}
disableRipple={expandLeftNav ? false : true} 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 <span
style={{ style={{
display: expandLeftNav ? "inline" : "none", display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0, opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease", transition: "opacity 0.3s ease",
color: currentOpenTab === "apps" && currentPath.includes("/apps2") ? "#F1F1F1" : "#C8C8C8", color: currentOpenTab === "apps" && currentPath.includes("/apps") ? "#FFFFFF" : "#C8C8C8",
}} }}
> >
Apps Apps
@@ -1178,12 +1189,11 @@ useEffect(() => {
? "#2f2f2f" ? "#2f2f2f"
: "transparent"; : "transparent";
}} }}
disabled={!userdata?.support}
> >
<ShieldOutlinedIcon <ShieldOutlinedIcon
style={{ style={{
width: 16, width: 18,
height: 16, height: 18,
marginRight: expandLeftNav ? 10 : 0, marginRight: expandLeftNav ? 10 : 0,
color: userdata?.support ? "inherit" : "#6F6F6F", color: userdata?.support ? "inherit" : "#6F6F6F",
}} }}
@@ -1192,6 +1202,7 @@ useEffect(() => {
style={{ style={{
display: expandLeftNav ? "inline" : "none", display: expandLeftNav ? "inline" : "none",
marginRight: "auto", marginRight: "auto",
fontSize: 18,
color: userdata?.support color: userdata?.support
? currentOpenTab === "security" && currentPath.includes("/security") ? currentOpenTab === "security" && currentPath.includes("/security")
? "#F1F1F1" ? "#F1F1F1"
@@ -1278,7 +1289,7 @@ useEffect(() => {
}} }}
disabled={userdata?.support === false} 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>
<span <span
@@ -1286,6 +1297,7 @@ useEffect(() => {
display: expandLeftNav ? "inline" : "none", display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0, opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease", transition: "opacity 0.3s ease",
fontSize: 18,
color: color:
userdata?.support && currentOpenTab === "detection" && currentPath.includes("/detection") userdata?.support && currentOpenTab === "detection" && currentPath.includes("/detection")
? "#F1F1F1" ? "#F1F1F1"
@@ -1329,7 +1341,7 @@ useEffect(() => {
cursor: userdata?.support ? "pointer" : "not-allowed", 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>
<span <span
@@ -1337,6 +1349,7 @@ useEffect(() => {
display: expandLeftNav ? "inline" : "none", display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0, opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease", transition: "opacity 0.3s ease",
fontSize: 18,
color: color:
userdata?.support && currentOpenTab === "response" && currentPath.includes("/response") userdata?.support && currentOpenTab === "response" && currentPath.includes("/response")
? "#F1F1F1" ? "#F1F1F1"
@@ -1380,7 +1393,7 @@ useEffect(() => {
cursor: userdata?.support ? "pointer" : "not-allowed", 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>
<span <span
@@ -1388,6 +1401,7 @@ useEffect(() => {
display: expandLeftNav ? "inline" : "none", display: expandLeftNav ? "inline" : "none",
opacity: expandLeftNav ? 1 : 0, opacity: expandLeftNav ? 1 : 0,
transition: "opacity 0.3s ease", transition: "opacity 0.3s ease",
fontSize: 18,
color: color:
userdata?.support && currentOpenTab === "response" && currentPath.includes("/response") userdata?.support && currentOpenTab === "response" && currentPath.includes("/response")
? "#F1F1F1" ? "#F1F1F1"
@@ -1458,7 +1472,7 @@ useEffect(() => {
<Typography <Typography
style={{ style={{
color: "#CDCDCD", color: "#CDCDCD",
fontSize: 14, fontSize: 18,
padding: "8px 8px", padding: "8px 8px",
marginBottom: 10, marginBottom: 10,
}} }}
@@ -1688,7 +1702,7 @@ useEffect(() => {
}, },
transition: "opacity 0.3s ease", transition: "opacity 0.3s ease",
textTransform: "none", textTransform: "none",
fontSize: 16, fontSize: 18,
}} }}
disableElevation disableElevation
disableRipple disableRipple
@@ -1718,13 +1732,14 @@ useEffect(() => {
style={{ style={{
color: "#CDCDCD", color: "#CDCDCD",
margin: "0 5px", margin: "0 5px",
fontSize: 16, fontSize: 18,
whiteSpace: "nowrap", whiteSpace: "nowrap",
overflow: "hidden", overflow: "hidden",
textOverflow: "ellipsis", textOverflow: "ellipsis",
maxWidth: 150, maxWidth: 150,
textAlign: "center", textAlign: "center",
marginLeft: 10, marginLeft: 10,
}} }}
> >
{userdata?.username} {userdata?.username}
+210 -29
View File
@@ -24,6 +24,7 @@ import {
DialogActions, DialogActions,
CardContent, CardContent,
ButtonGroup, ButtonGroup,
DialogContentText,
} from "@mui/material"; } from "@mui/material";
import { useNavigate, Link } from "react-router-dom"; import { useNavigate, Link } from "react-router-dom";
@@ -42,19 +43,17 @@ import {
import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx"; import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx";
import { handlePayasyougo } from "../views/HandlePaymentNew.jsx" import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
import Billing from "./Billing.jsx";
const LicencePopup = (props) => { 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(); //const alert = useAlert();
let navigate = useNavigate(); 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 [selectedDealModalOpen, setSelectedDealModalOpen] = React.useState(false);
const [dealList, setDealList] = React.useState([]); const [dealList, setDealList] = React.useState([]);
const [dealName, setDealName] = React.useState(""); const [dealName, setDealName] = React.useState("");
const [dealAddress, setDealAddress] = React.useState(""); const [dealAddress, setDealAddress] = React.useState("");
const [dealType, setDealType] = React.useState("MSSP"); const [dealType, setDealType] = React.useState("MSSP");
const [selectedOrganization, setSelectedOrganization] = React.useState({});
const [dealCountry, setDealCountry] = React.useState("United States"); const [dealCountry, setDealCountry] = React.useState("United States");
const [dealCurrency, setDealCurrency] = React.useState("USD"); const [dealCurrency, setDealCurrency] = React.useState("USD");
const [dealStatus, setDealStatus] = React.useState("initiated"); const [dealStatus, setDealStatus] = React.useState("initiated");
@@ -63,8 +62,8 @@ const LicencePopup = (props) => {
const [dealerror, setDealerror] = React.useState(""); const [dealerror, setDealerror] = React.useState("");
const [variant, setVariant] = useState(0) const [variant, setVariant] = useState(0)
const [shuffleVariant, setShuffleVariant] = useState(isCloud ? 0 : 1) 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 parsedFields = maxFields === undefined ? 300 : maxFields
const initialShuffleVariant = isCloud ? 0 : 1; const initialShuffleVariant = isCloud ? 0 : 1;
const [paymentType, setPaymentType] = useState(0) const [paymentType, setPaymentType] = useState(0)
@@ -78,6 +77,12 @@ const LicencePopup = (props) => {
const [calculatedCost, setCalculatedCost] = useState("$600") const [calculatedCost, setCalculatedCost] = useState("$600")
const [selectedValue, setSelectedValue] = useState(100) const [selectedValue, setSelectedValue] = useState(100)
useEffect(() => {
if(selectedOrganization?.Billing?.Email !== BillingEmail) {
setBillingEmail(selectedOrganization?.Billing?.Email);
}
}, [selectedOrganization])
// Onprem // Onprem
const [calculatedCores, setCalculatedCores] = useState('600') const [calculatedCores, setCalculatedCores] = useState('600')
const [onpremSelectedValue, setOnpremSelectedValue] = useState(8) const [onpremSelectedValue, setOnpremSelectedValue] = useState(8)
@@ -101,7 +106,8 @@ const LicencePopup = (props) => {
"description": "Pay as you go", "description": "Pay as you go",
"features": [ "features": [
"Basic Support", "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, "limit": 10000,
} }
@@ -137,13 +143,14 @@ const LicencePopup = (props) => {
}) })
} }
const SubscriptionObject = (props) => { const SubscriptionObject = (props) => {
const { globalUrl, index, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, subscription, highlight, } = props; const { globalUrl, index, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, subscription, highlight, } = props;
const [signatureOpen, setSignatureOpen] = React.useState(false); const [signatureOpen, setSignatureOpen] = React.useState(false);
const [tosChecked, setTosChecked] = React.useState(subscription.eula_signed) const [tosChecked, setTosChecked] = React.useState(subscription.eula_signed)
const [hovered, setHovered] = React.useState(false) const [hovered, setHovered] = React.useState(false)
const [newBillingEmail, setNewBillingEmail] = useState('');
var top_text = "Base Cloud Access" var top_text = "Base Cloud Access"
if (subscription.limit === undefined && subscription.level === undefined || subscription.level === null || subscription.level === 0) { if (subscription.limit === undefined && subscription.level === undefined || subscription.level === null || subscription.level === 0) {
subscription.name = "Enterprise" subscription.name = "Enterprise"
@@ -191,6 +198,58 @@ const LicencePopup = (props) => {
// newPaperstyle.border = "1px solid #f85a3e" // 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 ( return (
<Tooltip <Tooltip
style={{ borderRadius: theme.palette?.borderRadius, }} style={{ borderRadius: theme.palette?.borderRadius, }}
@@ -308,7 +367,7 @@ const LicencePopup = (props) => {
color="primary" color="primary"
/> />
: null} : 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} {top_text}
</Typography> </Typography>
@@ -343,7 +402,7 @@ const LicencePopup = (props) => {
</div> </div>
<Divider /> <Divider />
<div> <div>
<Typography variant="body1" style={{ marginTop: 20, }}> <Typography variant="body1" style={{ marginTop: 20,whiteSpace: 'nowrap' }}>
{subscription.name} {subscription.name}
</Typography> </Typography>
@@ -443,21 +502,141 @@ const LicencePopup = (props) => {
}) })
: null} : null}
</ul> </ul>
{isCloud ? <Typography variant="body2" color="textSecondary" style={{ marginTop: 20, marginBottom: 10 }}>
<span>Billing email: {selectedOrganization.org}</span> {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} : null}
</div> </div>
<Button <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",
}}
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>
<Button
variant="outlined"
style={{ style={{
marginLeft: 115, marginTop: 10,
marginTop: 50, borderRadius: 4,
borderRadius: 20, width: "100%",
width: 120,
color: "#FFFFFF",
cursor: "pointer", cursor: "pointer",
textTransform: "capitalize", textTransform: "capitalize",
backgroundColor: "transparent", backgroundColor: "transparent",
fontSize: 16,
position: "relative", // Required for positioning tooltip position: "relative", // Required for positioning tooltip
}} }}
title="Click to book a call" title="Click to book a call"
@@ -476,7 +655,7 @@ const LicencePopup = (props) => {
// } // }
}} }}
> >
<span style={{color: "#f85a3e",}}> <span>
Book a call Book a call
</span> </span>
<span <span
@@ -499,7 +678,6 @@ const LicencePopup = (props) => {
</span> </span>
</Button> </Button>
</Paper> </Paper>
{/* {/*
<div style={{ paddingRight: 150, display: "flex", alignItems: "baseline" }}> <div style={{ paddingRight: 150, display: "flex", alignItems: "baseline" }}>
@@ -736,7 +914,7 @@ const LicencePopup = (props) => {
return ( return (
<div> <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}> <Grid item xs={8}>
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? {isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ?
<SubscriptionObject <SubscriptionObject
@@ -895,13 +1073,11 @@ const LicencePopup = (props) => {
</div> </div>
</div> </div>
<div style={{ marginTop: 20, }} /> <div style={{ marginTop: 20, }} />
</Card> <DialogActions style={{ marginTop: 15 }} >
</Grid> <div style={{display: 'flex', flexDirection: 'column', width: "100%", justifyContent: 'space-between', gap: "10px"}}>
</Grid>
</Grid>
<DialogActions style={{ marginTop: 15 }} >
<Button <Button
style={{ borderRadius: "0px", textTransform: "capitalize" }} style={{ borderRadius: "4px", textTransform: "capitalize", width: "100%", fontSize: 16}}
variant="outlined"
onClick={() => { onClick={() => {
if (isCloud) { if (isCloud) {
ReactGA.event({ ReactGA.event({
@@ -914,7 +1090,6 @@ const LicencePopup = (props) => {
} else { } else {
window.open("https://shuffler.io/pricing?tab=onprem", "_blank") window.open("https://shuffler.io/pricing?tab=onprem", "_blank")
} }
setModalOpen(false)
}} }}
color="primary" color="primary"
> >
@@ -922,7 +1097,7 @@ const LicencePopup = (props) => {
</Button> </Button>
<Button <Button
variant="contained" variant="contained"
style={{ borderRadius: 20, width: 120, textTransform: "capitalize" }} style={{ borderRadius: 4, textTransform: "capitalize", color: "#1a1a1a", backgroundColor: "#ff8544", width: "100%", fontSize: 16}}
onClick={() => { onClick={() => {
if (isCloud) { if (isCloud) {
ReactGA.event({ ReactGA.event({
@@ -937,6 +1112,7 @@ const LicencePopup = (props) => {
navigate(`/register?view=pricing&message=You need to create a user to continue`) navigate(`/register?view=pricing&message=You need to create a user to continue`)
} }
} else { } else {
console.log("window.drift: ", window.drift)
if (window.drift !== undefined) { if (window.drift !== undefined) {
window.drift.api.startInteraction({ window.drift.api.startInteraction({
interactionId: 386403, interactionId: 386403,
@@ -948,7 +1124,12 @@ const LicencePopup = (props) => {
> >
Upgrade Upgrade
</Button> </Button>
</div>
</DialogActions> </DialogActions>
</Card>
</Grid>
</Grid>
</Grid>
</div> </div>
) )
} }
+122 -54
View File
@@ -255,7 +255,7 @@ const Priorities = memo((props) => {
onClick={() => { onClick={() => {
clearNotifications() clearNotifications()
}} }}
style={{marginLeft: 50, }} style={{marginLeft: 50, textTransform: "none", fontSize: 16}}
> >
Mark all as read Mark all as read
</Button> </Button>
@@ -265,7 +265,7 @@ const Priorities = memo((props) => {
{clickedFromOrgTab? null : <Divider style={{marginTop: 50, marginBottom: 50, }} />} {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> <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; 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 <a
target="_blank" target="_blank"
@@ -431,64 +431,132 @@ const NotificationItem = memo((props) => {
: :
null 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} {data.description}
</Typography > </Typography >
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
<ButtonGroup> <Button
<Button style={{
color="secondary" marginTop: 15,
variant="outlined" textTransform: "none",
style={{ marginTop: 15 }} fontSize: 16,
disabled={data.reference_url === undefined || data.reference_url === null || data.reference_url.length === 0} marginRight: 5,
onClick={() => { border: "1px solid #ff8544",
window.open(data.reference_url, "_blank") color: "#ff8544",
}} width: 130,
> opacity: data.reference_url ? 1 : 0.5,
Explore cursor: data.reference_url ? "pointer" : "not-allowed",
</Button> }}
{data.read === false ? ( disabled={
<Button !data.reference_url || data.reference_url.length === 0
color="secondary" }
variant="outlined" onClick={() => {
style={{ marginTop: 15 }} window.open(data.reference_url, "_blank");
onClick={() => { }}
dismissNotification(data.id); >
}} Explore
> </Button>
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>
<Typography variant="body2" color="textSecondary" style={{ marginLeft: 20, marginTop: 20, wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis" }}> {data.read === false ? (
<b>First seen</b>: {new Date(data.created_at * 1000).toISOString().slice(0, 19)} <Button
</Typography > sx={{
marginTop: "15px",
border: "none",
textTransform: "none",
fontSize: 16,
color: "#ffffff",
marginRight: "5px",
backgroundColor: "transparent",
"&:hover": { backgroundColor: "transparent" },
}}
onClick={() => {
dismissNotification(data.id);
}}
>
Dismiss
</Button>
) : null}
<Typography variant="body2" color="textSecondary" style={{ marginLeft: 20, marginTop: 20, wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis" }}> <Tooltip
<b>Last seen</b>: {new Date(data.updated_at * 1000).toISOString().slice(0, 19)} 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."
</Typography > placement="top"
>
<Button
style={{
marginTop: 15,
textTransform: "none",
fontSize: 16,
width: 130,
border: data.ignored
? "1px solid #2bc07e"
: "1px solid #ff8544",
color: data.ignored ? "#ffffff" : "#ff8544",
backgroundColor: data.ignored ? "#2bc07e" : "transparent",
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>
<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> </Paper>
); );
}) })
+1 -1
View File
@@ -154,7 +154,7 @@ const Priority = (props) => {
} }
</div> </div>
<div style={{flex: 1, display: "flex", marginLeft: 30, }}> <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) { if (isCloud) {
ReactGA.event({ ReactGA.event({
+3 -2
View File
@@ -238,7 +238,7 @@ const Admin2 = (props) => {
const data = { const data = {
name: name, name: name,
description: description, description: description,
org_id: orgId, org_id: orgId?.length > 0 ? orgId : selectedOrganization?.id,
image: image, image: image,
defaults: defaults, defaults: defaults,
sso_config: sso_config, sso_config: sso_config,
@@ -263,6 +263,7 @@ const Admin2 = (props) => {
if (responseJson["success"] === false) { if (responseJson["success"] === false) {
toast("Failed updating org: ", responseJson.reason); toast("Failed updating org: ", responseJson.reason);
} else { } else {
handleGetOrg(selectedOrganization?.id);
if ( if (
lead_info === undefined || lead_info === undefined ||
lead_info === null || lead_info === null ||
@@ -329,7 +330,7 @@ const Admin2 = (props) => {
} }
return ( 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} /> <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> </div>
); );
+100 -81
View File
@@ -20,14 +20,18 @@ import {
IconButton, IconButton,
} from "@mui/material"; } from "@mui/material";
import { Context } from "../context/ContextApi.jsx"; import { Context } from "../context/ContextApi.jsx";
import Add from '@mui/icons-material/Add';
import CachedIcon from '@mui/icons-material/Cached'; import {
import CloudDownloadIcon from '@mui/icons-material/CloudDownload'; Add as AddIcon,
import EditIcon from '@mui/icons-material/Edit'; 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 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 { ClearRefinements, connectHits, connectSearchBox, connectStateResults, InstantSearch, RefinementList, connectRefinementList, Configure } from "react-instantsearch-dom";
import { removeQuery } from "../components/ScrollToTop.jsx"; import { removeQuery } from "../components/ScrollToTop.jsx";
@@ -45,7 +49,7 @@ const searchClient = algoliasearch(
); );
// AppCard Component // 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 navigate = useNavigate();
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "localhost:3000"; 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}`; 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, fontWeight: 600,
whiteSpace: "nowrap", whiteSpace: "nowrap",
marginLeft: 8, marginLeft: 8,
maxWidth: "90%",
gap: 8 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>
<div style={{ <div style={{
overflow: "hidden", overflow: "hidden",
@@ -182,12 +194,13 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
<Button <Button
className="deactivate-button" className="deactivate-button"
sx={{ sx={{
width: 102, width: 110,
height: 35, height: 35,
borderRadius: 0.75, borderRadius: 0.75,
bgcolor: "rgba(73, 73, 73, 1)", bgcolor: "rgba(73, 73, 73, 1)",
color: "rgba(241, 241, 241, 1)", color: "rgba(241, 241, 241, 1)",
textTransform: "none", textTransform: "none",
fontSize: 16,
fontFamily: theme?.typography?.fontFamily, fontFamily: theme?.typography?.fontFamily,
transition: "background-color 0.3s ease", transition: "background-color 0.3s ease",
"&:hover": { "&:hover": {
@@ -213,6 +226,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
toast.error(responseJson.reason); toast.error(responseJson.reason);
} else { } else {
toast.success("App Deactivated Successfully."); toast.success("App Deactivated Successfully.");
fetchApps();
} }
}) })
.catch(error => { .catch(error => {
@@ -445,13 +459,21 @@ const Hits = ({
overflow: "hidden", overflow: "hidden",
gap: 8, gap: 8,
fontWeight: 600, fontWeight: 600,
maxWidth: "90%",
textOverflow: "ellipsis", textOverflow: "ellipsis",
whiteSpace: "nowrap", whiteSpace: "nowrap",
color: '#F1F1F1' color: '#F1F1F1'
}} }}
> >
{(allActivatedAppIds && allActivatedAppIds.includes(data.objectID)) && <Box sx={{ width: 8, height: 8, backgroundColor: "#02CB70", borderRadius: '50%' }} />} {(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>
<div <div
@@ -535,18 +557,19 @@ const Hits = ({
paddingRight: 10, paddingRight: 10,
minWidth: 110 minWidth: 110
}}> }}>
{hoverEffect === index && isCloud && ( {hoverEffect === index && (
<div> <div>
{allActivatedAppIds && allActivatedAppIds.includes(data.objectID) ? ( {allActivatedAppIds && allActivatedAppIds.includes(data.objectID) ? (
<Button <Button
style={{ style={{
width: 102, width: 110,
height: 35, height: 35,
borderRadius: 3, borderRadius: 4,
backgroundColor: "rgba(73, 73, 73, 1)", backgroundColor: "rgba(73, 73, 73, 1)",
color: "rgba(241, 241, 241, 1)", color: "rgba(241, 241, 241, 1)",
textTransform: "none", textTransform: "none",
fontFamily: theme?.typography?.fontFamily, fontFamily: theme?.typography?.fontFamily,
fontSize: 16,
}} }}
onClick={(event) => { onClick={(event) => {
handleActivateButton(event, data, "deactivate"); handleActivateButton(event, data, "deactivate");
@@ -560,9 +583,10 @@ const Hits = ({
color: "black", color: "black",
width: 102, width: 102,
height: 35, height: 35,
borderRadius: 3, borderRadius: 4,
textTransform: "none", textTransform: "none",
fontFamily: theme?.typography?.fontFamily, fontFamily: theme?.typography?.fontFamily,
fontSize: 16
}} }}
onClick={(event) => { onClick={(event) => {
handleActivateButton(event, data, "activate"); handleActivateButton(event, data, "activate");
@@ -655,15 +679,15 @@ const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
event.preventDefault(); 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={{ InputProps={{
style: { style: {
borderRadius: 8, borderRadius: 4,
height: 45 height: 45
}, },
endAdornment: ( endAdornment: (
<InputAdornment position="end"> <InputAdornment position="end">
{localQuery?.length === 0 ? <Search /> : ( {localQuery?.length === 0 ? <SearchIcon /> : (
<ClearIcon <ClearIcon
style={{ style={{
cursor: "pointer", cursor: "pointer",
@@ -703,7 +727,7 @@ const CategoryDropdown = ({ items, currentRefinement, refine }) => {
onChange={handleChange} onChange={handleChange}
displayEmpty displayEmpty
multiple 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) => { renderValue={(selected) => {
if (selected.length === 0) return 'All Categories'; if (selected.length === 0) return 'All Categories';
return ( return (
@@ -764,7 +788,7 @@ const LabelDropdown = ({ items, currentRefinement, refine }) => {
onChange={handleChange} onChange={handleChange}
displayEmpty displayEmpty
multiple 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) => { renderValue={(selected) => {
if (selected.length === 0) return 'All Labels'; if (selected.length === 0) return 'All Labels';
return ( return (
@@ -855,7 +879,7 @@ const AppSkeleton = () => {
backgroundColor: "#212121", backgroundColor: "#212121",
width: "100%", width: "100%",
height: 120, height: 120,
borderRadius: 8, borderRadius: 4,
}}> }}>
<div style={{ <div style={{
display: "flex", display: "flex",
@@ -868,7 +892,7 @@ const AppSkeleton = () => {
width={100} width={100}
height={90} height={90}
style={{ style={{
borderRadius: 6, borderRadius: 4,
backgroundColor: "rgba(255, 255, 255, 0.1)" 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 // Fetch apps based on the current tab : 0 -> org_apps, 1 -> my_apps, 2 -> all_apps
useEffect(() => { const fetchApps = async () => {
const fetchApps = async () => { const baseUrl = globalUrl;
const baseUrl = globalUrl; let url;
let url; setIsLoading(true);
setIsLoading(true); const userId = userdata?.id;
const userId = userdata?.id; if (currTab === 1 && userId) {
if (currTab === 1 && userId) { url = `${baseUrl}/api/v1/users/${userId}/apps`;
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) { } else if (currTab === 0) {
url = `${baseUrl}/api/v1/apps`; setAppsToShow(data);
setOrgApps(data);
// For testing the empty state
// setAppsToShow([]);
// setOrgApps([]);
} }
try { setIsLoading(false);
const response = await fetch(url, { } catch (err) {
method: "GET", console.error("Error fetching apps:", err);
credentials: "include", setIsLoading(false);
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);
}
};
useEffect(() => {
// Only fetch if we have required data // Only fetch if we have required data
if (globalUrl && (currTab === 0 || (currTab === 1 && userdata?.id))) { if (globalUrl && (currTab === 0 || (currTab === 1 && userdata?.id))) {
@@ -1164,15 +1188,16 @@ const Apps2 = (props) => {
return response.json(); return response.json();
}) })
.then((responseJson) => { .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 privateapps = [];
var valid = []; var valid = [];
var invalid = []; var invalid = [];
for (var key in responseJson) { for (var key in responseJson) {
const app = responseJson[key]; 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)) { if (app.is_valid && !(!app.activated && app.generated)) {
privateapps.push(app); privateapps.push(app);
} else if ( } 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(...valid);
privateapps.push(...invalid); privateapps.push(...invalid);
console.log("privateapps: setting apps ", privateapps) console.log("privateapps: setting apps ", privateapps)
setAppsToShow(privateapps); setAppsToShow(privateapps);
setOrgApps(privateapps); setOrgApps(privateapps);
setApps(privateapps); setApps(privateapps);
// setCursearch("");
//handleSearchChange(event.target.value)
//setCursearch(event.target.value)
// setFilteredApps(privateapps); // setFilteredApps(privateapps);
if (privateapps.length > 0) { if (privateapps.length > 0) {
if (selectedApp.id === undefined || selectedApp.id === null) { if (selectedApp.id === undefined || selectedApp.id === null) {
@@ -1708,7 +1725,7 @@ const Apps2 = (props) => {
} }
return ( 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"> <InstantSearch searchClient={searchClient} indexName="appsearch">
<AppModal <AppModal
open={openModal} open={openModal}
@@ -1755,7 +1772,7 @@ const Apps2 = (props) => {
height: 45, height: 45,
minWidth: 45, minWidth: 45,
backgroundColor: "#2F2F2F", backgroundColor: "#2F2F2F",
borderRadius: 8, borderRadius: 4,
padding: "8px 16px", padding: "8px 16px",
}} }}
disabled={isLoading} disabled={isLoading}
@@ -1795,7 +1812,7 @@ const Apps2 = (props) => {
height: 45, height: 45,
minWidth: 45, minWidth: 45,
backgroundColor: "#2F2F2F", backgroundColor: "#2F2F2F",
borderRadius: 8, borderRadius: 4,
padding: "8px 16px", padding: "8px 16px",
}} }}
disabled={isLoading} disabled={isLoading}
@@ -1821,11 +1838,11 @@ const Apps2 = (props) => {
value={currTab} value={currTab}
onChange={(event, newTab) => handleTabChange(event, newTab)} onChange={(event, newTab) => handleTabChange(event, newTab)}
TabIndicatorProps={{ style: { height: '3px', borderRadius: 10, backgroundColor: "#FF8544" } }} TabIndicatorProps={{ style: { height: '3px', borderRadius: 10, backgroundColor: "#FF8544" } }}
style={{ fontFamily: theme?.typography?.fontFamily }} style={{ fontFamily: theme?.typography?.fontFamily, fontSize: 16 }}
> >
<Tab label="Organization Apps" style={{ textTransform: 'none', marginRight: 20, fontFamily: theme?.typography?.fontFamily }} /> <Tab label="Organization Apps" style={{ textTransform: 'none', marginRight: 20, fontFamily: theme?.typography?.fontFamily, fontSize: 16 }} />
<Tab label="My Apps" style={{ textTransform: 'none', marginRight: 20, fontFamily: theme?.typography?.fontFamily }} /> <Tab label="My Apps" style={{ textTransform: 'none', marginRight: 20, fontFamily: theme?.typography?.fontFamily, fontSize: 16 }} />
<Tab label="Discover Apps" style={{ textTransform: 'none', fontFamily: theme?.typography?.fontFamily }} /> <Tab label="Discover Apps" style={{ textTransform: 'none', fontFamily: theme?.typography?.fontFamily, fontSize: 16 }} />
</Tabs> </Tabs>
</div> </div>
<div style={{ display: "flex", justifyContent: "space-between", gap: 10, marginBottom: 20, height: 45, paddingRight: 25 }}> <div style={{ display: "flex", justifyContent: "space-between", gap: 10, marginBottom: 20, height: 45, paddingRight: 25 }}>
@@ -1850,12 +1867,12 @@ const Apps2 = (props) => {
limit={5} limit={5}
InputProps={{ InputProps={{
style: { style: {
borderRadius: 8, borderRadius: 4,
height: 45 height: 45
}, },
endAdornment: ( endAdornment: (
<InputAdornment position="end"> <InputAdornment position="end">
{searchQuery.length === 0 ? <Search /> : ( {searchQuery.length === 0 ? <SearchIcon /> : (
<ClearIcon <ClearIcon
style={{ cursor: "pointer" }} style={{ cursor: "pointer" }}
onClick={() => { onClick={() => {
@@ -1892,7 +1909,7 @@ const Apps2 = (props) => {
displayEmpty displayEmpty
multiple multiple
style={{ style={{
borderRadius: 8, borderRadius: 4,
height: 45, height: 45,
fontFamily: theme?.typography?.fontFamily fontFamily: theme?.typography?.fontFamily
}} }}
@@ -1956,7 +1973,7 @@ const Apps2 = (props) => {
displayEmpty displayEmpty
multiple multiple
style={{ style={{
borderRadius: 8, borderRadius: 4,
height: 45, height: 45,
fontFamily: theme?.typography?.fontFamily fontFamily: theme?.typography?.fontFamily
}} }}
@@ -2014,7 +2031,7 @@ const Apps2 = (props) => {
style={{ style={{
height: "100%", height: "100%",
width: '100%', width: '100%',
borderRadius: '7px', borderRadius: '4px',
textTransform: 'none', textTransform: 'none',
backgroundColor: "#FF8544", backgroundColor: "#FF8544",
color: "#1A1A1A", color: "#1A1A1A",
@@ -2022,7 +2039,7 @@ const Apps2 = (props) => {
fontSize: 16, fontSize: 16,
fontWeight: 500 fontWeight: 500
}} }}
startIcon={<Add style={{ color: "#1A1A1A" }} />} startIcon={<AddIcon style={{ color: "#1A1A1A" }} />}
> >
Create an App Create an App
</Button> </Button>
@@ -2062,6 +2079,7 @@ const Apps2 = (props) => {
handleAppClick={handleAppClick} handleAppClick={handleAppClick}
leftSideBarOpenByClick={leftSideBarOpenByClick} leftSideBarOpenByClick={leftSideBarOpenByClick}
userdata={userdata} userdata={userdata}
fetchApps={fetchApps}
/> />
))} ))}
</div> </div>
@@ -2106,6 +2124,7 @@ const Apps2 = (props) => {
{appsToShow.map((data, index) => ( {appsToShow.map((data, index) => (
<AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} currTab={currTab} userdata={userdata} <AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} currTab={currTab} userdata={userdata}
handleAppClick={handleAppClick} leftSideBarOpenByClick={leftSideBarOpenByClick} handleAppClick={handleAppClick} leftSideBarOpenByClick={leftSideBarOpenByClick}
fetchApps={fetchApps}
/> />
))} ))}
</div> </div>
File diff suppressed because it is too large Load Diff