Tons of minor fixes
This commit is contained in:
@@ -476,7 +476,7 @@ const LoginPage = props => {
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.pathname = "/workflows"
|
||||
window.location.pathname = "/new-dashboard"
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
@@ -658,7 +658,7 @@ const LoginPage = props => {
|
||||
}
|
||||
}
|
||||
|
||||
window.location.pathname = "/workflows"
|
||||
window.location.pathname = "/new-dashboard"
|
||||
}, 2000);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -10,22 +10,31 @@ import {
|
||||
Divider,
|
||||
Select,
|
||||
MenuItem,
|
||||
Tooltip,
|
||||
CircularProgress,
|
||||
} from '@mui/material';
|
||||
import TrendingUpIcon from '@mui/icons-material/TrendingUp';
|
||||
import TrendingDownIcon from '@mui/icons-material/TrendingDown';
|
||||
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
|
||||
import TaskAltIcon from '@mui/icons-material/TaskAlt';
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
|
||||
import {
|
||||
TrendingFlat as TrendingFlatIcon,
|
||||
TrendingUp as TrendingUpIcon,
|
||||
TrendingDown as TrendingDownIcon,
|
||||
TaskAlt as TaskAltIcon,
|
||||
SuccessFailed as SuccessFailedIcon,
|
||||
RunsOverTime as RunsOverTimeIcon,
|
||||
ErrorOutline as ErrorOutlineIcon,
|
||||
} from '@mui/icons-material';
|
||||
|
||||
import SuccessFailedRunsWidget from '../components/SuccessFailedRunsWidget.jsx';
|
||||
import RunsOverTimeWidget from '../components/RunsOverTimeWidget.jsx';
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import DashboardOnboarding from '../components/DashboardOnboarding.jsx';
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
const NewDashboard = (props) => {
|
||||
const { globalUrl, userdata } = props;
|
||||
const { globalUrl, serverside, userdata } = props;
|
||||
|
||||
// const [workflows, setWorkflows] = useState([]);
|
||||
const { leftSideBarOpenByClick } = useContext(Context);
|
||||
const [sfwControls, setSfwControls] = useState(null);
|
||||
const [loadingSfw, setLoadingSfw] = useState(true);
|
||||
@@ -40,9 +49,18 @@ const NewDashboard = (props) => {
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
const [overrideDays, setOverrideDays] = useState(undefined);
|
||||
const [rotMonthOverride, setRotMonthOverride] = useState(undefined);
|
||||
const [isProdStatusOn, setIsProdStatusOn] = useState(false)
|
||||
|
||||
const isCloud =
|
||||
serverside === true || typeof window === "undefined"
|
||||
? true
|
||||
: window.location.host === "localhost:3002" ||
|
||||
window.location.host === "shuffler.io" ||
|
||||
window.location.host === "localhost:5002";
|
||||
|
||||
const navigate = useNavigate();
|
||||
const handleSfwControls = useCallback((node) => {
|
||||
@@ -71,8 +89,6 @@ const NewDashboard = (props) => {
|
||||
};
|
||||
|
||||
const timeFmt = formatTimeDisplay(totals.timeSavedMinutes);
|
||||
const STATIC_TIME_PERCENT = '62%';
|
||||
const STATIC_MONEY_PERCENT = '46%';
|
||||
|
||||
const unreadCount = notifications.filter(n => n && n.read === false).length;
|
||||
const readCount = notifications.filter(n => n && n.read === true).length;
|
||||
@@ -81,9 +97,11 @@ const NewDashboard = (props) => {
|
||||
// 1 Workflow run = 15 minutes
|
||||
// 1 Workflow run = $25
|
||||
|
||||
const STATIC_TIME_PERCENT = 'TBD'
|
||||
const STATIC_MONEY_PERCENT = 'TBD'
|
||||
const kpis = [
|
||||
{ value: timeFmt.display, title: timeFmt.title, label: 'Time saved', icon: <TrendingUpIcon sx={{ color: '#5cc879', fontSize: 34 }} />, percentage: STATIC_TIME_PERCENT, color: '#5cc879' },
|
||||
{ value: formatCurrencyCompact(totals.moneySavedDollars), label: 'Money saved', icon: <TrendingUpIcon sx={{ color: '#5cc879', fontSize: 34 }} />, percentage: STATIC_MONEY_PERCENT, color: '#5cc879' },
|
||||
{ value: timeFmt.display, title: timeFmt.title, label: 'Time saved', icon: <TrendingUpIcon sx={{ color: '#5cc879', fontSize: 34 }} />, percentage: STATIC_TIME_PERCENT, color: '#5cc879', disabled: true},
|
||||
{ value: formatCurrencyCompact(totals.moneySavedDollars), label: 'Money saved', icon: <TrendingUpIcon sx={{ color: '#5cc879', fontSize: 34 }} />, percentage: STATIC_MONEY_PERCENT, color: '#5cc879', disabled: true, },
|
||||
{ value: String(unreadCount), label: 'Total errors', icon: <ErrorOutlineIcon sx={{ color: '#f87171', fontSize: 34, opacity: 0.9 }} />, percentage: "", color: '#f87171' },
|
||||
{ value: String(readCount), label: 'Errors resolved', icon: <TaskAltIcon sx={{ color: '#5cc879', fontSize: 34, opacity: 0.9 }} />, percentage: "", color: '#5cc879' },
|
||||
];
|
||||
@@ -177,13 +195,51 @@ const NewDashboard = (props) => {
|
||||
|
||||
// loadWorkflows();
|
||||
// }, [globalUrl]);
|
||||
|
||||
useEffect(() => {
|
||||
const orgId = userdata?.active_org?.id;
|
||||
if (!orgId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let fetched = false;
|
||||
fetch(`${globalUrl}/api/v1/orgs/${orgId}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
.then((response) => (response.ok ? response.json() : null))
|
||||
.then((org) => {
|
||||
if (!fetched && org) {
|
||||
if (!isCloud) {
|
||||
if (org?.cloud_sync && org?.subscriptions[0]?.name?.toLowerCase().includes("enterprise") && org?.subscriptions[0]?.active) {
|
||||
setIsProdStatusOn(true);
|
||||
} else if (org?.subscriptions[0]?.name?.toLowerCase().includes("enterprise") && org?.subscriptions[0]?.active) {
|
||||
setIsProdStatusOn(true);
|
||||
} else {
|
||||
setIsProdStatusOn(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
return () => {
|
||||
fetched = true;
|
||||
};
|
||||
}, [userdata?.active_org?.id, globalUrl]);
|
||||
|
||||
return (
|
||||
<div style={{ maxWidth: 1366, margin: '0 auto', padding: 16, paddingTop: 50, paddingBottom: 30, paddingLeft: leftSideBarOpenByClick ? 270 : 80, transition: 'padding-left 0.3s ease', position: 'relative' }}>
|
||||
<DashboardOnboarding
|
||||
open={onboardingOpen}
|
||||
globalUrl={globalUrl}
|
||||
onClose={() => setOnboardingOpen(false)}
|
||||
onClose={() => {
|
||||
setOnboardingOpen(false)
|
||||
}}
|
||||
setOnboardingOpen={setOnboardingOpen}
|
||||
isProdStatusOn={isProdStatusOn}
|
||||
isCloud={isCloud}
|
||||
onExplore={() => {
|
||||
// Ensure overrides are set before closing modal
|
||||
setOverrideDays(5);
|
||||
@@ -215,28 +271,31 @@ const NewDashboard = (props) => {
|
||||
<Grid container spacing={2}>
|
||||
{kpis.map((kpi) => (
|
||||
<Grid item xs={12} sm={6} md={3} key={kpi.label}>
|
||||
<Paper style={{ padding: 16, background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 12
|
||||
,cursor: kpi.label.toLowerCase().includes('total errors') ? 'pointer' : 'default'
|
||||
}}
|
||||
onClick={() => {
|
||||
if (kpi.label.toLowerCase().includes('total errors')) {
|
||||
// navigate to notifications page
|
||||
navigate('/admin?admin_tab=notifications');
|
||||
}
|
||||
}}
|
||||
|
||||
>
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between">
|
||||
<Stack sx={{py:2, paddingLeft: 1}}>
|
||||
<Typography variant="h4" title={kpi.title || ''}>{kpi.value}</Typography>
|
||||
<Typography sx={{fontSize: 13}} color="textSecondary">{kpi.label}</Typography>
|
||||
</Stack>
|
||||
<Stack sx={{py: 2, paddingRight: 1, marginTop: kpi.label.toLowerCase().includes('errors') ? -1 : 0}}>
|
||||
{kpi.icon}
|
||||
<Typography variant="body2" color={kpi.color}>{kpi.percentage}</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Paper>
|
||||
<Tooltip title={kpi.disabled ? "This metric is coming soon!" : ""} arrow>
|
||||
<Paper style={{ padding: 16, background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 12
|
||||
, cursor: kpi.label.toLowerCase().includes('total errors') ? 'pointer' : 'default',
|
||||
transparency: kpi.disabled ? 0.5 : 1
|
||||
}}
|
||||
onClick={() => {
|
||||
if (kpi.label.toLowerCase().includes('total errors')) {
|
||||
// navigate to notifications page
|
||||
navigate('/admin?admin_tab=notifications');
|
||||
}
|
||||
}}
|
||||
|
||||
>
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between">
|
||||
<Stack sx={{py:2, paddingLeft: 1}}>
|
||||
<Typography variant="h4" title={kpi.title || ''}>{kpi.value}</Typography>
|
||||
<Typography sx={{fontSize: 13}} color="textSecondary">{kpi.label}</Typography>
|
||||
</Stack>
|
||||
<Stack sx={{py: 2, paddingRight: 1, marginTop: kpi.label.toLowerCase().includes('errors') ? -1 : 0}}>
|
||||
{kpi.icon}
|
||||
<Typography variant="body2" color={kpi.color}>{kpi.percentage}</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
@@ -818,6 +818,7 @@ const Workflows2 = (props) => {
|
||||
const [highlightIds, setHighlightIds] = React.useState([])
|
||||
|
||||
const [apps, setApps] = React.useState([]);
|
||||
const [isProdStatusOn, setIsProdStatusOn] = React.useState(false);
|
||||
|
||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||
|
||||
@@ -839,6 +840,39 @@ const Workflows2 = (props) => {
|
||||
}
|
||||
}, [location.search]);
|
||||
|
||||
useEffect(() => {
|
||||
const orgId = userdata?.active_org?.id;
|
||||
if (!orgId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let fetched = false;
|
||||
fetch(`${globalUrl}/api/v1/orgs/${orgId}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
.then((response) => (response.ok ? response.json() : null))
|
||||
.then((org) => {
|
||||
if (!fetched && org) {
|
||||
if (!isCloud) {
|
||||
if (org?.cloud_sync && org?.subscriptions[0]?.name?.toLowerCase().includes("enterprise") && org?.subscriptions[0]?.active) {
|
||||
setIsProdStatusOn(true);
|
||||
} else if (org?.subscriptions[0]?.name?.toLowerCase().includes("enterprise") && org?.subscriptions[0]?.active) {
|
||||
setIsProdStatusOn(true);
|
||||
} else {
|
||||
setIsProdStatusOn(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
return () => {
|
||||
fetched = true;
|
||||
};
|
||||
}, [userdata?.active_org?.id, globalUrl]);
|
||||
|
||||
const handleTabChange = (event, newValue) => {
|
||||
setCurrTab(newValue);
|
||||
|
||||
@@ -3043,12 +3077,34 @@ const Workflows2 = (props) => {
|
||||
}
|
||||
}
|
||||
|
||||
const isPublicWorkflow = data?.objectId === undefined || data?.objectId === null
|
||||
const foundImage = !isPublicWorkflow ? "" : data?.image_url === undefined || data?.image_url === null || data?.image_url === "" ? data?.image : data?.image_url
|
||||
|
||||
const foundTimeline = workflowTimelines.find((timeline) => timeline.id === data.id)
|
||||
return (
|
||||
<div
|
||||
id={`workflowbox-${data.id}`}
|
||||
style={{ width: "100%", minWidth: 320, position: "relative", border: highlightIds.includes(data.id) ? "2px solid #f85a3e" : isDistributed || hasSuborgs ? `2px solid ${theme.palette.distributionColor}` : "inherit", borderRadius: theme.palette?.borderRadius, backgroundColor: "#212121", fontFamily: theme.typography?.fontFamily }}>
|
||||
style={{ width: "100%", minWidth: 320, position: "relative", border: highlightIds.includes(data.id) ? "2px solid #f85a3e" : isDistributed || hasSuborgs ? `2px solid ${theme.palette.distributionColor}` : "inherit", borderRadius: theme.palette?.borderRadius, backgroundColor: "#212121", fontFamily: theme.typography?.fontFamily, overflow: "hidden", }}
|
||||
>
|
||||
|
||||
{isPublicWorkflow && foundImage?.length > 0 ?
|
||||
<img src={foundImage} alt="image" style={{
|
||||
maxHeight: 250,
|
||||
minHeight: 250,
|
||||
minWidth: 100,
|
||||
marginLeft: 12,
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => {
|
||||
if (isCloud) {
|
||||
navigate(`/workflows/${data.objectID}`)
|
||||
} else {
|
||||
window.open(`https://shuffler.io/workflows/${data.objectID}`, "_blank")
|
||||
}
|
||||
}}
|
||||
/>
|
||||
: null}
|
||||
|
||||
<Paper square style={paperAppStyle}>
|
||||
{selectedCategory !== "" ?
|
||||
<Tooltip title={`Usecase Category: ${selectedCategory}`} placement="bottom">
|
||||
@@ -4934,7 +4990,7 @@ const Workflows2 = (props) => {
|
||||
}}
|
||||
/>
|
||||
<Tab
|
||||
label="Discover Workflows"
|
||||
label="Community Workflows"
|
||||
style={{
|
||||
...tabStyle,
|
||||
marginRight: 0,
|
||||
@@ -5313,12 +5369,58 @@ const Workflows2 = (props) => {
|
||||
</div>
|
||||
}
|
||||
|
||||
{!isCloud ? (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 20,
|
||||
padding: "4px 10px",
|
||||
marginLeft: "5px",
|
||||
marginRight: "5px",
|
||||
borderRadius: 20,
|
||||
marginBottom: "14px",
|
||||
background: isProdStatusOn
|
||||
? "rgba(43, 192, 126, 0.1)"
|
||||
: "rgba(255, 82, 82, 0.1)",
|
||||
cursor: "pointer",
|
||||
position: "absolute",
|
||||
top: 20,
|
||||
right: 20,
|
||||
}}
|
||||
onClick={() => {
|
||||
navigate("/admin?admin_tab=billingstats")
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
marginLeft: 10,
|
||||
background: isProdStatusOn ? "#2BC07E" : "#FD4C62",
|
||||
borderRadius: 999,
|
||||
display: "inline",
|
||||
}}
|
||||
/>
|
||||
<Typography
|
||||
style={{
|
||||
fontFamily: "12px",
|
||||
opacity: 0.9,
|
||||
color: isProdStatusOn ? "#2BC07E" : "#FD4C62",
|
||||
}}
|
||||
>
|
||||
{isProdStatusOn ? "Production" : "NOT Production"}
|
||||
</Typography>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div style={{
|
||||
width: "100%",
|
||||
position: "relative",
|
||||
zIndex: 1
|
||||
}}>
|
||||
|
||||
|
||||
{
|
||||
(isLoadingWorkflow && currTab !== 2) ? (
|
||||
<LoadingWorkflowGrid />
|
||||
|
||||
Reference in New Issue
Block a user