Lightmode/Darkmode merge including many fixes since 2.0.2
This commit is contained in:
@@ -23,7 +23,7 @@ require (
|
||||
github.com/h2non/filetype v1.1.3
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/shuffle/shuffle-shared v0.8.50
|
||||
golang.org/x/crypto v0.36.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
google.golang.org/api v0.228.0
|
||||
google.golang.org/grpc v1.71.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 0L-1.48522e-08 13.3913L4.40052 13.3913L4.40052 4.46465L22 4.46465L22 2.44001e-08L0 0Z" fill="#FF8444"/>
|
||||
<path d="M17.5995 8.60864L17.5995 17.5353L-9.90052e-09 17.5353L-1.48522e-08 22L22 22L22 8.60864L17.5995 8.60864Z" fill="#FF8444"/>
|
||||
<path d="M13.3915 8.60864L8.60889 8.60864L8.60889 13.3913L13.3915 13.3913L13.3915 8.60864Z" fill="#FF8444"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 459 B |
@@ -19,17 +19,97 @@ import {
|
||||
FmdGoodOutlined as FmdGoodOutlinedIcon,
|
||||
GroupOutlined as GroupOutlinedIcon
|
||||
} from '@mui/icons-material';
|
||||
import theme from '../theme.jsx';
|
||||
import { Button, Tooltip } from '@mui/material';
|
||||
import theme, { getTheme } from '../theme.jsx';
|
||||
import { Button, Skeleton, Tooltip } from '@mui/material';
|
||||
import { Index } from 'react-instantsearch-dom';
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
const AdminNavBar = (props) => {
|
||||
const location = useLocation();
|
||||
const { globalUrl, userdata, isCloud, isLoaded,removeCookie, handleStatusChange, selectedStatus, setSelectedStatus, handleEditOrg, serverside, notifications, handleGetOrg, orgId, checkLogin, setNotifications, stripeKey, setSelectedOrganization, selectedOrganization } = props;
|
||||
const { globalUrl, userdata, isCloud,isOrgLoaded, isLoaded,removeCookie, handleStatusChange, selectedStatus, setSelectedStatus, handleEditOrg, serverside, notifications, handleGetOrg, orgId, checkLogin, setNotifications, stripeKey, setSelectedOrganization, selectedOrganization } = props;
|
||||
const [selectedItem, setSelectedItem] = useState("Organization");
|
||||
const [isSelectedFiles, setIsSelectedFiles] = useState(true);
|
||||
const [isSelectedDataStore, setIsSelectedDataStore] = useState(true);
|
||||
const [isIntegrationPartner, setIsIntegrationPartner] = useState(false);
|
||||
const [isChildOrg, setIsChildOrg] = useState(false);
|
||||
const [isGlobalUser, setIsGlobalUser] = useState(false);
|
||||
const [visibleItems, setVisibleItems] = useState([]);
|
||||
const [isUserDataLoaded, setIsUserDataLoaded] = useState(false);
|
||||
|
||||
const items = [
|
||||
{ iconSrc: <BusinessIcon />, alt: "Organization Icon", text: "Organization", component: OrganizationTab, props: { isIntegrationPartner, isChildOrg, isGlobalUser, globalUrl,removeCookie, selectedStatus, isLoaded, setSelectedStatus, handleStatusChange, handleEditOrg, handleGetOrg, userdata, isCloud, serverside, notifications, checkLogin, setNotifications, stripeKey, setSelectedOrganization, selectedOrganization } },
|
||||
{ iconSrc: <PermIdentityIcon />, alt: "Users Icon", text: "Users", component: UserManagmentTab, props: { globalUrl, userdata, serverside, isCloud, selectedOrganization, setSelectedOrganization, handleEditOrg } },
|
||||
{ iconSrc: <HttpsOutlinedIcon />, alt: "App Auth Icon", text: "App_auth", component: AppAuthTab, props: { globalUrl, userdata, isCloud, selectedOrganization } },
|
||||
{ iconSrc: <StorageOutlinedIcon />, alt: "Datastore Icon", text: "Datastore", component: CacheView, props: { globalUrl, userdata, selectedOrganization, serverside, isSelectedDataStore, orgId , isCloud} },
|
||||
{ iconSrc: <InsertDriveFileOutlinedIcon />, alt: "Files Icon", text: "Files", component: Files, props: { isCloud, globalUrl, userdata, serverside, selectedOrganization, isSelectedFiles } },
|
||||
{ iconSrc: <AccessTimeOutlinedIcon />, alt: "Trigger Icon", text: "Triggers", component: SchedulesTab, props: { globalUrl, userdata, isCloud, serverside } },
|
||||
{ iconSrc: <FmdGoodOutlinedIcon />, alt: "Environments Icon", text: "Locations", component: EnvironmentTab, props: { globalUrl, userdata, isCloud, selectedOrganization } },
|
||||
{ iconSrc: <GroupOutlinedIcon />, alt: "Tenants Icon", text: "Tenants", component: TenantsTab, props: {isCloud, globalUrl, userdata, serverside, selectedOrganization, setSelectedOrganization, checkLogin } }
|
||||
];
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (userdata && userdata?.active_org?.id?.length > 0) {
|
||||
setIsUserDataLoaded(true);
|
||||
}
|
||||
}, [userdata]);
|
||||
|
||||
|
||||
|
||||
const { themeMode, brandColor } = React.useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
const HandlePartnerChange = () => {
|
||||
if (userdata?.id?.length > 0) {
|
||||
const isIntegrationPartner = userdata?.org_status?.includes("integration_partner") || false;
|
||||
setIsIntegrationPartner(isIntegrationPartner);
|
||||
const isChildOrg = userdata?.org_status?.includes("sub_org") || false;
|
||||
setIsChildOrg(isChildOrg);
|
||||
const isGlobalUser = userdata?.active_org?.branding?.global_user || false;
|
||||
setIsGlobalUser(isGlobalUser);
|
||||
} else {
|
||||
setIsIntegrationPartner(false);
|
||||
setIsChildOrg(false);
|
||||
setIsGlobalUser(false);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (userdata && userdata?.id?.length > 0) {
|
||||
HandlePartnerChange();
|
||||
}
|
||||
}, [userdata]);
|
||||
|
||||
const HandleVisibleTabs = () => {
|
||||
if (userdata?.id?.length > 0) {
|
||||
if (userdata?.active_org?.role === "admin" || userdata?.support) {
|
||||
setVisibleItems(items);
|
||||
}else {
|
||||
const filteredItems = items.filter(item => item.text !== "Users" && item.text !== "Files" && item.text !== "Datastore" && item.text !== "Triggers" && item.text !== "Locations");
|
||||
setVisibleItems(filteredItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isIntegrationPartner && isChildOrg && !isGlobalUser) {
|
||||
// Filter out Users and Tenants tabs
|
||||
if (userdata?.active_org?.role === "admin" || userdata?.support) {
|
||||
const filteredItems = items.filter(item =>
|
||||
item.text !== "Users" && item.text !== "Tenants"
|
||||
);
|
||||
setVisibleItems(filteredItems);
|
||||
}else {
|
||||
const filteredItems = items.filter(item =>
|
||||
item.text !== "Users" && item.text !== "Tenants" && item.text !== "Files" && item.text !== "Datastore" && item.text !== "Triggers" && item.text !== "Locations"
|
||||
);
|
||||
setVisibleItems(filteredItems);
|
||||
}
|
||||
} else {
|
||||
HandleVisibleTabs();
|
||||
}
|
||||
}, [isIntegrationPartner, isChildOrg, isGlobalUser, selectedOrganization, userdata]);
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -53,18 +133,6 @@ const AdminNavBar = (props) => {
|
||||
}
|
||||
}, [location.search]);
|
||||
|
||||
|
||||
const items = [
|
||||
{ iconSrc: <BusinessIcon />, alt: "Organization Icon", text: "Organization", component: OrganizationTab, props: { globalUrl,removeCookie, selectedStatus, isLoaded, setSelectedStatus, handleStatusChange, handleEditOrg, handleGetOrg, userdata, isCloud, serverside, notifications, checkLogin, setNotifications, stripeKey, setSelectedOrganization, selectedOrganization } },
|
||||
{ iconSrc: <PermIdentityIcon />, alt: "Users Icon", text: "Users", component: UserManagmentTab, props: { globalUrl, userdata, serverside, isCloud, selectedOrganization, setSelectedOrganization, handleEditOrg } },
|
||||
{ iconSrc: <HttpsOutlinedIcon />, alt: "App Auth Icon", text: "App_auth", component: AppAuthTab, props: { globalUrl, userdata, isCloud, selectedOrganization } },
|
||||
{ iconSrc: <StorageOutlinedIcon />, alt: "Datastore Icon", text: "Datastore", component: CacheView, props: { globalUrl, userdata, selectedOrganization, serverside, isSelectedDataStore, orgId , isCloud} },
|
||||
{ iconSrc: <InsertDriveFileOutlinedIcon />, alt: "Files Icon", text: "Files", component: Files, props: { isCloud, globalUrl, userdata, serverside, selectedOrganization, isSelectedFiles } },
|
||||
{ iconSrc: <AccessTimeOutlinedIcon />, alt: "Trigger Icon", text: "Triggers", component: SchedulesTab, props: { globalUrl, userdata, isCloud, serverside } },
|
||||
{ iconSrc: <FmdGoodOutlinedIcon />, alt: "Environments Icon", text: "Locations", component: EnvironmentTab, props: { globalUrl, userdata, isCloud, selectedOrganization } },
|
||||
{ iconSrc: <GroupOutlinedIcon />, alt: "Tenants Icon", text: "Tenants", component: TenantsTab, props: {isCloud, globalUrl, userdata, serverside, selectedOrganization, setSelectedOrganization, checkLogin } }
|
||||
];
|
||||
|
||||
const setConfig = (newValue) => {
|
||||
setSelectedItem(newValue);
|
||||
if (newValue === "App Auth") {
|
||||
@@ -76,12 +144,65 @@ const AdminNavBar = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isIntegrationPartner && isChildOrg && !isGlobalUser && isOrgLoaded && isUserDataLoaded) {
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
const tabName = queryParams?.get('admin_tab')?.toLowerCase();
|
||||
if (tabName === "sso" || tabName === "branding") {
|
||||
toast.info("You are not allowed to access this tab. Please contact your admin for more information. Redirecting to Organization Configuration tab.");
|
||||
setTimeout(() => {
|
||||
setSelectedItem("Organization");
|
||||
navigate(`?admin_tab=org_config`, { replace: true });
|
||||
window.location.reload();
|
||||
}
|
||||
, 3000);
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
const tab = params?.get('tab')?.toLowerCase();
|
||||
if (tab === "users" || tab === "tenants") {
|
||||
toast.info("You are not allowed to access this tab. Please contact your admin for more information. Redirecting to Organization Configuration tab.");
|
||||
setTimeout(() => {
|
||||
setSelectedItem("Organization");
|
||||
navigate(`?admin_tab=org_config`, { replace: true });
|
||||
window.location.reload();
|
||||
}
|
||||
, 3000);
|
||||
}
|
||||
} else if (userdata && isOrgLoaded && isUserDataLoaded && userdata?.active_org?.role !== "admin" && !userdata?.support) {
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
const tabName = queryParams?.get('admin_tab')?.toLowerCase();
|
||||
if (tabName === "sso") {
|
||||
toast.info("You are not allowed to access this tab. Please contact your admin for more information. Redirecting to Organization Configuration tab.");
|
||||
setTimeout(() => {
|
||||
setSelectedItem("Organization");
|
||||
navigate(`?admin_tab=org_config`, { replace: true });
|
||||
window.location.reload();
|
||||
}
|
||||
, 3000);
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
const tab = params?.get('tab')?.toLowerCase();
|
||||
if (tab === "users" || tab === "locations" || tab === "environments" || tab === "files" || tab === "datastore" || tab === "triggers") {
|
||||
toast.info("You are not allowed to access this tab. Please contact your admin for more information. Redirecting to Organization Configuration tab.");
|
||||
setTimeout(() => {
|
||||
setSelectedItem("Organization");
|
||||
navigate(`?admin_tab=org_config`, { replace: true });
|
||||
window.location.reload();
|
||||
}
|
||||
, 3000);
|
||||
}
|
||||
}
|
||||
}, [isIntegrationPartner, isChildOrg, isGlobalUser, location.search, userdata, isOrgLoaded, isUserDataLoaded]);
|
||||
|
||||
|
||||
const renderComponent = () => {
|
||||
const selectedItemData = items.find(item => item.text === selectedItem);
|
||||
const selectedItemData = visibleItems.find(item => item.text === selectedItem);
|
||||
if (!selectedItemData) {
|
||||
setSelectedItem("Organization");
|
||||
// If no tab is specified, default to "Organization" tab
|
||||
return <OrganizationTab globalUrl={globalUrl} removeCookie={removeCookie} selectedStatus={selectedStatus} isLoaded={isLoaded} setSelectedStatus={setSelectedStatus} handleStatusChange={handleStatusChange} handleEditOrg={handleEditOrg} handleGetOrg={handleGetOrg} userdata={userdata} isCloud={isCloud} serverside={serverside} notifications={notifications} checkLogin={checkLogin} setNotifications={setNotifications} stripeKey={stripeKey} setSelectedOrganization={setSelectedOrganization} selectedOrganization={selectedOrganization}/>;
|
||||
return <OrganizationTab isIntegrationPartner={isIntegrationPartner} isChildOrg={isChildOrg} isGlobalUser={isGlobalUser} globalUrl={globalUrl} removeCookie={removeCookie} selectedStatus={selectedStatus} isLoaded={isLoaded} setSelectedStatus={setSelectedStatus} handleStatusChange={handleStatusChange} handleEditOrg={handleEditOrg} handleGetOrg={handleGetOrg} userdata={userdata} isCloud={isCloud} serverside={serverside} notifications={notifications} checkLogin={checkLogin} setNotifications={setNotifications} stripeKey={stripeKey} setSelectedOrganization={setSelectedOrganization} selectedOrganization={selectedOrganization}/>;
|
||||
};
|
||||
|
||||
const ComponentToRender = selectedItemData.component;
|
||||
@@ -97,15 +218,16 @@ const AdminNavBar = (props) => {
|
||||
: selectedOrganization?.image;
|
||||
|
||||
return (
|
||||
!isOrgLoaded && !isUserDataLoaded ? <Loader /> :
|
||||
<Wrapper>
|
||||
<div style={{ flexDirection: 'column', width: 220, }}>
|
||||
<nav style={{ padding: '25px 25px 3px 25px', height: isCloud ? "calc(100% - 60px)" : "calc(100% - 30px)" , fontSize: '16px', borderTopLeftRadius: 8, borderBottomLeftRadius: 8, background: '#212121', color: '#9CA3AF' }}>
|
||||
<nav style={{ padding: '25px 25px 3px 25px', height: isCloud ? "calc(100% - 60px)" : "calc(100% - 30px)" , fontSize: '16px', borderTopLeftRadius: 8, borderBottomLeftRadius: 8, background: theme.palette.platformColor, color: '#9CA3AF' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', }}>
|
||||
<img loading="lazy" src={imageData} alt="Logo" style={{ width: '30px', borderRadius: 8, height: '30px', marginRight: '8px' }} />
|
||||
<div style={{
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontSize: '16px',
|
||||
color: "#FFFFFF",
|
||||
color: theme.palette.text.primary,
|
||||
fontWeight: 400,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
@@ -114,8 +236,8 @@ const AdminNavBar = (props) => {
|
||||
marginLeft: 5,
|
||||
}}>{selectedOrganization?.name}</div>
|
||||
</div>
|
||||
<div style={{ borderTop: '1px solid #494949', marginTop: 23 }} />
|
||||
{items.map((item, index) => (
|
||||
<div style={{ borderTop: theme.palette.defaultBorder, marginTop: 23 }} />
|
||||
{visibleItems.map((item, index) => (
|
||||
<Tooltip
|
||||
key={index}
|
||||
title={
|
||||
@@ -132,11 +254,10 @@ const AdminNavBar = (props) => {
|
||||
color="primary"
|
||||
sx={{
|
||||
gap: 1,
|
||||
"&:hover": {
|
||||
backgroundColor: "#323232 !important",
|
||||
},
|
||||
"&.MuiButton-root": {
|
||||
color: selectedItem === item.text ? "#FFFFFF" : "#9E9E9E",
|
||||
color: selectedItem === item.text
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary,
|
||||
fontSize: 16,
|
||||
backgroundColor: "transparent",
|
||||
textTransform: "none",
|
||||
@@ -149,13 +270,16 @@ const AdminNavBar = (props) => {
|
||||
justifyContent: "flex-start",
|
||||
borderLeft:
|
||||
selectedItem === item.text
|
||||
? "3px solid rgba(255, 132, 68, 1)"
|
||||
? `3px solid ${theme.palette.primary.main}`
|
||||
: "none",
|
||||
borderTopLeftRadius: selectedItem === item.text ? "2.5px" : null,
|
||||
borderBottomLeftRadius: selectedItem === item.text ? "2.5px" : null,
|
||||
paddingLeft: selectedItem === item.text ? "15px" : "10px",
|
||||
fontWeight: selectedItem === item.text ? 200 : "normal",
|
||||
flex: 1,
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor,
|
||||
},
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
color: "#6F6F6F",
|
||||
@@ -183,6 +307,112 @@ const AdminNavBar = (props) => {
|
||||
|
||||
export default AdminNavBar;
|
||||
|
||||
const Loader = () => {
|
||||
const dummyItems = Array.from({ length: 6 });
|
||||
const dummyNavItems = Array.from({ length: 6 });
|
||||
const dummyTabItems = ['Org Configuration', 'SSO', 'Notifications', 'Billing & Stats', 'Branding'];
|
||||
const { leftSideBarOpenByClick, windowWidth, themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
return (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
minHeight: '100vh',
|
||||
maxWidth: '1200px',
|
||||
fontFamily: 'Arial, sans-serif',
|
||||
paddingLeft: leftSideBarOpenByClick ? windowWidth <= 1300 ? 220 : 200 : 80,
|
||||
transition: "padding-left 0.3s ease",
|
||||
}}>
|
||||
|
||||
<div style={{
|
||||
width: '220px',
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
borderTopLeftRadius: '8px',
|
||||
borderBottomLeftRadius: '8px',
|
||||
padding: '25px 25px 3px 25px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
}}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', marginBottom: '20px' }}>
|
||||
<Skeleton
|
||||
width="30px"
|
||||
height="30px"
|
||||
sx={{ borderRadius: '8px', marginRight: '8px', }}
|
||||
/>
|
||||
<Skeleton width="120px" height="24px" />
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<Skeleton
|
||||
width="100%"
|
||||
height="1px"
|
||||
sx={{ marginBottom: '15px' }}
|
||||
/>
|
||||
|
||||
{/* Nav Items */}
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '5px', width: '100%' }}>
|
||||
{dummyNavItems.map((_, index) => (
|
||||
<div key={index} style={{ display: 'flex', alignItems: 'center', padding: '5px 0' }}>
|
||||
<Skeleton
|
||||
width="18px"
|
||||
height="18px"
|
||||
sx={{ marginRight: '10px' }}
|
||||
/>
|
||||
<Skeleton width={`${100 + Math.random() * 40}px`} height="36px" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{
|
||||
flex: 1,
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
borderTopRightRadius: '8px',
|
||||
borderBottomRightRadius: '8px',
|
||||
borderLeft: theme.palette.defaultBorder,
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
}}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
padding: '0 16px'
|
||||
}}>
|
||||
{dummyTabItems.map((_, index) => (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: '28px 0',
|
||||
borderBottom: index === 0 ? '2px solid #FF8444' : 'none'
|
||||
}}
|
||||
>
|
||||
<Skeleton width={`${80 + Math.random() * 30}px`} height="24px" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div style={{ flex: 1, padding: '24px' }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', width: '100%', margin: '0 auto', alignItems: 'flex-start' }}>
|
||||
<Skeleton variant='square' width="200px" height="200px" sx={{ marginBottom: '20px' }} />
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px', width: '100%', marginTop: '50px' }}>
|
||||
{dummyItems.map((_, index) => (
|
||||
<div key={index} style={{ display: 'flex', alignItems: 'center', width: '100%' }}>
|
||||
<Skeleton width={'400px'} height="36px" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const PaddingWrapper2 = memo(({ children }) => {
|
||||
|
||||
return (
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import throttle from "lodash/throttle";
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import { validateJson, collapseField, } from "../views/Workflows.jsx";
|
||||
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
@@ -37,6 +37,8 @@ import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
function CustomTabPanel(props) {
|
||||
const { children, value, index, ...other } = props;
|
||||
const {themeMode} = useContext(Context);
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -47,7 +49,7 @@ function CustomTabPanel(props) {
|
||||
{...other}
|
||||
>
|
||||
{value === index && (
|
||||
<Box sx={{ p: 3, padding: 0, backgroundColor: "#1a1a1a" }}>
|
||||
<Box sx={{ p: 3, padding: 0, backgroundColor: theme.palette.backgroundColor}}>
|
||||
{children}
|
||||
</Box>
|
||||
)}
|
||||
@@ -100,6 +102,8 @@ const ApiExplorer = memo(({ openapi, globalUrl, userdata, HandleApiExecution, se
|
||||
const [selectedActionIndex, setSelectedActionIndex] = useState(0);
|
||||
const [ExampleBody, setExampleBody] = useState({});
|
||||
const [filteredActions, setFilteredActions] = useState([]);
|
||||
const {themeMode} = useContext(Context);
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const [firstSendDone, setFirstSendDone] = useState(false)
|
||||
|
||||
@@ -1391,6 +1395,8 @@ const ActionsList = memo(({
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [visibleActions, setVisibleActions] = useState([]);
|
||||
const {themeMode} = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
@@ -1463,7 +1469,7 @@ const ActionsList = memo(({
|
||||
alt="app logo"
|
||||
style={{ marginLeft: 20, borderRadius: 8 }}
|
||||
/>
|
||||
<Typography style={{ fontSize: 24, fontWeight: 'bold', marginLeft: 20, overflow: 'hidden', color: '#F1F1F1'
|
||||
<Typography style={{ fontSize: 24, fontWeight: 'bold', marginLeft: 20, overflow: 'hidden', color: theme.palette.textColor
|
||||
}}>
|
||||
{info.title}
|
||||
</Typography>
|
||||
@@ -1471,7 +1477,7 @@ const ActionsList = memo(({
|
||||
</Tooltip>
|
||||
</a>
|
||||
) : (
|
||||
<Typography style={{ fontSize: 24, fontWeight: 'bold', marginLeft: 20, overflow: 'hidden', color: '#F1F1F1'
|
||||
<Typography style={{ fontSize: 24, fontWeight: 'bold', marginLeft: 20, overflow: 'hidden', color: theme.palette.textColor
|
||||
}}>
|
||||
Api Explorer
|
||||
</Typography>
|
||||
@@ -1504,7 +1510,7 @@ const ActionsList = memo(({
|
||||
style={{
|
||||
marginLeft: 20,
|
||||
marginTop: 15,
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
overflowY: "auto",
|
||||
height: (isLoaded && isLoggedIn) ? "calc(100vh - 190px)" : "calc(100vh - 260px)",
|
||||
paddingRight: 5,
|
||||
@@ -1522,7 +1528,7 @@ const ActionsList = memo(({
|
||||
textTransform: "none",
|
||||
backgroundColor:
|
||||
selectedActionIndex === actionIndex
|
||||
? "#3f3f3f"
|
||||
? theme.palette.hoverColor
|
||||
: "transparent",
|
||||
border: "none",
|
||||
justifyContent: "flex-start",
|
||||
@@ -1535,7 +1541,7 @@ const ActionsList = memo(({
|
||||
textWrap: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
"&:hover": {
|
||||
backgroundColor: "#2f2f2f",
|
||||
backgroundColor: theme.palette.hoverColor,
|
||||
},
|
||||
}}
|
||||
onClick={() => handleActionClick(actionIndex, action)}
|
||||
@@ -1554,7 +1560,7 @@ const ActionsList = memo(({
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
textOverflow: "ellipsis",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
@@ -1564,7 +1570,7 @@ const ActionsList = memo(({
|
||||
</Button>
|
||||
))
|
||||
) : (
|
||||
<div style={{ padding: "15px", color: "white", textAlign: "center" }}>
|
||||
<div style={{ padding: "15px", color: theme.palette.textColor, textAlign: "center" }}>
|
||||
No actions found
|
||||
</div>
|
||||
)}
|
||||
@@ -1602,6 +1608,8 @@ const Action = memo((
|
||||
const [disableExecuteButton, setDisableExecuteButton] = useState(false);
|
||||
const [showResponseLoader, setShowResponseLoader] = useState(false);
|
||||
const [appAuthentication, setAppAuthentication] = useState([])
|
||||
const {themeMode} = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
const parseHeaders = (headersString) => {
|
||||
if (headersString?.length > 0) {
|
||||
const headersArray = headersString.split("\n");
|
||||
@@ -2082,7 +2090,7 @@ const Action = memo((
|
||||
fontWeight: 700,
|
||||
marginLeft: 40,
|
||||
marginBottom: 5,
|
||||
color: "rgba(241, 241, 241, 1)",
|
||||
color: theme.palette.textColor
|
||||
}}
|
||||
>
|
||||
{actionname}
|
||||
@@ -2095,7 +2103,7 @@ const Action = memo((
|
||||
borderRadius: 6,
|
||||
marginLeft: "40px",
|
||||
marginTop: 2,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
height: 51,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
@@ -2109,7 +2117,7 @@ const Action = memo((
|
||||
backgroundColor: "transparent",
|
||||
"& .MuiSelect-select": {
|
||||
color: RequestMethods.find((method) => method.value === selectedMethod)
|
||||
?.color || "#212121",
|
||||
?.color || theme.palette.textFieldStyle.backgroundColor,
|
||||
},
|
||||
}}
|
||||
MenuProps={{
|
||||
@@ -2117,14 +2125,14 @@ const Action = memo((
|
||||
sx: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
},
|
||||
},
|
||||
MenuListProps: {
|
||||
sx: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
},
|
||||
},
|
||||
}}
|
||||
@@ -2135,20 +2143,20 @@ const Action = memo((
|
||||
value={method.value}
|
||||
sx={{
|
||||
color: method.color,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
border: "none",
|
||||
marginBottom: 0.25,
|
||||
"&:hover": {
|
||||
backgroundColor: method.color,
|
||||
color: "#f9fcf5",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
"&.Mui-selected": {
|
||||
backgroundColor: method.color,
|
||||
color: "#f9fcf5",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
border: "none",
|
||||
"&:hover": {
|
||||
backgroundColor: method.color,
|
||||
color: "#f9fcf5",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
},
|
||||
"&.Mui-focusVisible": {
|
||||
@@ -2167,9 +2175,8 @@ const Action = memo((
|
||||
inputProps={{
|
||||
style: {
|
||||
margin: "auto",
|
||||
backgroundColor: "transparent",
|
||||
border: "none",
|
||||
color: "rgba(241, 241, 241, 1)",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
display: 'flex',
|
||||
height: '100%',
|
||||
alignItems: 'center',
|
||||
@@ -2331,7 +2338,7 @@ const Action = memo((
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
background: "rgba(26, 26, 26, 1)",
|
||||
background: theme.palette.backgroundColor,
|
||||
}}
|
||||
>
|
||||
<Tabs
|
||||
@@ -2386,7 +2393,7 @@ const Action = memo((
|
||||
<TableContainer
|
||||
style={{
|
||||
minWidth: 696,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
borderRadius: 6,
|
||||
border: "1px solid rgba(73, 73, 73, 1)",
|
||||
}}
|
||||
@@ -2436,7 +2443,7 @@ const Action = memo((
|
||||
}
|
||||
inputProps={{
|
||||
style: {
|
||||
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
padding: "4px 8px",
|
||||
},
|
||||
}}
|
||||
@@ -2494,7 +2501,7 @@ const Action = memo((
|
||||
</InputAdornment>
|
||||
),
|
||||
style: {
|
||||
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
padding: "4px 8px",
|
||||
},
|
||||
}}
|
||||
@@ -2600,7 +2607,7 @@ const Action = memo((
|
||||
<TableContainer
|
||||
style={{
|
||||
minWidth: 696,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
borderRadius: 6,
|
||||
border: "1px solid rgba(73, 73, 73, 1)",
|
||||
}}
|
||||
@@ -2640,7 +2647,7 @@ const Action = memo((
|
||||
type="text"
|
||||
inputProps={{
|
||||
style: {
|
||||
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||
backgroundColor: theme.palette.platformColor ,
|
||||
padding: "4px 8px",
|
||||
},
|
||||
}}
|
||||
@@ -2694,7 +2701,7 @@ const Action = memo((
|
||||
value={row.value}
|
||||
inputProps={{
|
||||
style: {
|
||||
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
padding: "4px 8px",
|
||||
},
|
||||
}}
|
||||
@@ -2794,10 +2801,10 @@ const Action = memo((
|
||||
marginLeft: 10
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: 16, fontWeight: 600 }}>
|
||||
<span style={{ fontSize: 16, fontWeight: 600, color: theme.palette.textColor }}>
|
||||
{action.name.replaceAll("_", " ")}
|
||||
</span>
|
||||
<p >
|
||||
<p style={{color: theme.palette.textColor}}>
|
||||
{action.description
|
||||
? action.description
|
||||
: ""}
|
||||
@@ -2813,6 +2820,8 @@ const ActionResponse = memo(({ apiResponse, ExampleBody, isLoggedIn, isLoaded })
|
||||
const [responseTabIndex, setResponseTabIndex] = useState(0)
|
||||
const [oldResponse, setOldResponse] = useState(apiResponse)
|
||||
const [highlight, setHighlight] = useState(false)
|
||||
const {themeMode } = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const MIN_HEIGHT = 50
|
||||
|
||||
@@ -2934,7 +2943,7 @@ const ActionResponse = memo(({ apiResponse, ExampleBody, isLoggedIn, isLoaded })
|
||||
style={{
|
||||
width: '100%',
|
||||
height: height,
|
||||
backgroundColor: '#1a1a1a',
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
borderTop: '1px solid rgba(255,255,255,0.2)',
|
||||
@@ -2988,7 +2997,7 @@ const ActionResponse = memo(({ apiResponse, ExampleBody, isLoggedIn, isLoaded })
|
||||
<ReactJson
|
||||
src={formData(ExampleBody)}
|
||||
theme={theme.palette.jsonTheme}
|
||||
style={{ backgroundColor: '#1a1a1a', padding: 5 }}
|
||||
style={{...theme.palette.reactJsonStyle, border: "none"}}
|
||||
collapsed={false}
|
||||
iconStyle={theme.palette.jsonIconStyle}
|
||||
collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength}
|
||||
@@ -3005,6 +3014,10 @@ const ActionResponse = memo(({ apiResponse, ExampleBody, isLoggedIn, isLoaded })
|
||||
});
|
||||
|
||||
const ResponseTabWrapper = memo(({ apiResponse }) => {
|
||||
|
||||
const {themeMode } = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const handleReactJsonClipboard = (copy) => {
|
||||
const elementName = "copy_element_shuffle";
|
||||
let copyText = document.getElementById(elementName);
|
||||
@@ -3036,7 +3049,7 @@ const ResponseTabWrapper = memo(({ apiResponse }) => {
|
||||
<ReactJson
|
||||
src={apiResponse}
|
||||
theme={theme.palette.jsonTheme}
|
||||
style={{ backgroundColor: "#1a1a1a", padding: 5 }}
|
||||
style={{...theme.palette.reactJsonStyle, border: "none"}}
|
||||
shouldCollapse={(jsonField) => {
|
||||
return collapseField(jsonField)
|
||||
}}
|
||||
@@ -3049,7 +3062,8 @@ const ResponseTabWrapper = memo(({ apiResponse }) => {
|
||||
)})
|
||||
|
||||
const PaddingWrapper = memo(({ isLoggedIn, isLoaded, children }) => {
|
||||
const { leftSideBarOpenByClick, windowWidth } = useContext(Context);
|
||||
const { leftSideBarOpenByClick, windowWidth, themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode)
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -3058,7 +3072,7 @@ const PaddingWrapper = memo(({ isLoggedIn, isLoaded, children }) => {
|
||||
? windowWidth >= 1920 ? "calc(100% - 630px)" : "calc(100% - 570px)"
|
||||
: windowWidth >= 1920 ? "calc(100vw - 460px)": "calc(100% - 410px)"
|
||||
: windowWidth >= 1920 ? "calc(100% - 370px)" : "calc(100% - 320px)",
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
position: "fixed",
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from "@mui/icons-material";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import Markdown from "react-markdown";
|
||||
import AuthenticationOauth2 from "../components/Oauth2Auth.jsx";
|
||||
import { isMobile } from "react-device-detect"
|
||||
@@ -89,6 +89,8 @@ const AppAuthTab = memo((props) => {
|
||||
const [showAppModal, setShowAppModal] = useState(false)
|
||||
const [showAuthenticationLoader, setShowAuthenticationLoader] = useState(true)
|
||||
const [showAppAuthGroupLoader, setShowAppAuthGroupLoader] = useState(true)
|
||||
const { themeMode, supportEmail, brandColor } = useContext(Context)
|
||||
const theme = getTheme(themeMode, brandColor)
|
||||
const changeDistribution = (data) => {
|
||||
//changeDistributed(data, !isDistributed)
|
||||
editAuthenticationConfig(data.id, "suborg_distribute")
|
||||
@@ -277,7 +279,7 @@ const AppAuthTab = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<span style={{ color: "white" }}>
|
||||
<span style={{ color: theme.palette.textColor }}>
|
||||
Edit authentication for {selectedAuthentication.app.name.replaceAll("_", " ")} (
|
||||
{selectedAuthentication.label})
|
||||
</span>
|
||||
@@ -297,7 +299,7 @@ const AppAuthTab = memo((props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: 50,
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -349,7 +351,7 @@ const AppAuthTab = memo((props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: 50,
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -568,7 +570,7 @@ const AppAuthTab = memo((props) => {
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success === false) {
|
||||
toast("Failed to create. Please try again, or contact support@shuffler.io")
|
||||
toast(`Failed to create. Please try again, or contact ${supportEmail}`)
|
||||
} else {
|
||||
// Close the modal
|
||||
setAppAuthenticationGroupModalOpen(false)
|
||||
@@ -660,7 +662,7 @@ const AppAuthTab = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<span style={{ color: "white" }}>App Authentication Groups</span>
|
||||
<span style={{ color: theme.palette.textColor }}>App Authentication Groups</span>
|
||||
</DialogTitle>
|
||||
|
||||
<DialogContent style={{marginLeft: 0, paddingLeft: 0, }}>
|
||||
@@ -677,7 +679,7 @@ const AppAuthTab = memo((props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
@@ -853,22 +855,22 @@ const AppAuthTab = memo((props) => {
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div style={{width: "100%", minHeight: 1100, maxHeight: 1700, overflowY: "auto", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin',boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121',borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949", }}>
|
||||
<div style={{width: "100%", minHeight: 1100, maxHeight: 1700, overflowY: "auto", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin',boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: theme.palette.platformColor,borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: theme.palette.defaultBorder, }}>
|
||||
{appModal}
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<div style={{ width: 'auto', display:'flex',}}>
|
||||
<div style={{display: 'flex', flexDirection: 'column'}}>
|
||||
<h2 style={{ marginBottom: 8, marginTop: 0, color: "#FFFFFF" }}>App Authentication</h2>
|
||||
<div>
|
||||
<span style={{}}>
|
||||
<Typography variant='h5' style={{ marginBottom: 8, marginTop: 0, }}>App Authentication</Typography>
|
||||
<div style={{display: 'flex', flexDirection: 'row', alignItems: 'center', }}>
|
||||
<Typography variant='body2' color="textSecondary">
|
||||
Control the authentication options for individual apps.
|
||||
</span>
|
||||
</Typography>
|
||||
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/organizations#app_authentication"
|
||||
style={{ color: "#FF8444" }}
|
||||
style={{ color: theme.palette.linkColor }}
|
||||
>
|
||||
Learn more about App Authentication
|
||||
</a>
|
||||
@@ -877,7 +879,7 @@ const AppAuthTab = memo((props) => {
|
||||
|
||||
{isCloud ?
|
||||
<Button
|
||||
style={{ color: '#1a1a1a', textTransform: 'none', backgroundColor: "#FF8444", marginLeft:"auto", borderRadius: 4,fontSize: 16, minWidth: 162, height: 40, boxShadow:'none', }}
|
||||
style={{ textTransform: 'none', marginLeft:"auto", borderRadius: 4,fontSize: 16, minWidth: 162, height: 40, boxShadow:'none', }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={!isCloud}
|
||||
@@ -899,7 +901,7 @@ const AppAuthTab = memo((props) => {
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.defaultBorder,
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
@@ -917,7 +919,7 @@ const AppAuthTab = memo((props) => {
|
||||
}}>
|
||||
|
||||
|
||||
<ListItem style={{ width: "100%", paddingTop: 10, paddingBottom: 10, paddingRight: 10, borderBottom: "1px solid #494949", display: 'table-row'}}>
|
||||
<ListItem style={{ width: "100%", paddingTop: 10, paddingBottom: 10, paddingRight: 10, borderBottom: theme.palette.defaultBorder, display: 'table-row'}}>
|
||||
|
||||
{["Valid", "Label", "App Name", "Workflows", "Fields", "Edited", "Actions", "Distribution"].map((header, index) => (
|
||||
<ListItemText
|
||||
@@ -928,7 +930,7 @@ const AppAuthTab = memo((props) => {
|
||||
padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
position: "sticky",
|
||||
}}
|
||||
/>
|
||||
@@ -942,7 +944,7 @@ const AppAuthTab = memo((props) => {
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "table-row",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
}}
|
||||
>
|
||||
{Array(8)
|
||||
@@ -959,7 +961,7 @@ const AppAuthTab = memo((props) => {
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
height: "20px",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
@@ -970,14 +972,14 @@ const AppAuthTab = memo((props) => {
|
||||
))
|
||||
: authentication?.length === 0 ? (
|
||||
<div style={{ textAlign: 'center'}}>
|
||||
<Typography style={{ color: "#FFFFFF", textAlign: 'center', padding: 20}}>
|
||||
<Typography color="textPrimary" style={{ textAlign: 'center', padding: 20}}>
|
||||
No authentication found.
|
||||
</Typography>
|
||||
</div>
|
||||
):authentication.map((data, index) => {
|
||||
var bgColor = "#212121";
|
||||
var bgColor = themeMode === "dark" ? "#212121" : "#FFFFFF";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = "#1A1A1A";
|
||||
bgColor = themeMode === "dark" ? "#1A1A1A" : "#EAEAEA";
|
||||
}
|
||||
|
||||
//console.log("Auth data: ", data)
|
||||
@@ -1059,7 +1061,7 @@ const AppAuthTab = memo((props) => {
|
||||
<ListItemText
|
||||
primary={
|
||||
<Tooltip title={"Try the app in our API explorer"} placement="top">
|
||||
<a href={`/apis/${data.app.id}`} style={{ color: "#FF8444", textDecoration: "none", cursor: "pointer", }} target="_blank" rel="noopener noreferrer">
|
||||
<a href={`/apis/${data.app.id}`} style={{ color: theme.palette.linkColor, textDecoration: "none", cursor: "pointer", }} target="_blank" rel="noopener noreferrer">
|
||||
{data?.app?.name?.replaceAll("_", " ")}
|
||||
</a>
|
||||
</Tooltip>
|
||||
@@ -1112,7 +1114,7 @@ const AppAuthTab = memo((props) => {
|
||||
style={{
|
||||
overflow: "hidden",
|
||||
display: "table-cell",
|
||||
verticalAlign: 'middle'
|
||||
verticalAlign: 'middle',
|
||||
}}
|
||||
primaryTypographyProps={{
|
||||
style: {
|
||||
@@ -1129,12 +1131,23 @@ const AppAuthTab = memo((props) => {
|
||||
primaryTypographyProps={{ style: { display: "flex", flexDirection: 'row', padding: 8 } }}
|
||||
>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
updateAppAuthentication(data);
|
||||
}}
|
||||
onClick={() => updateAppAuthentication(data)}
|
||||
disabled={data.org_id !== selectedOrganization.id}
|
||||
>
|
||||
<img src="/icons/editIcon.svg" alt="Edit icon" color="secondary" />
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.1038 4.66848C16.3158 4.45654 16.5674 4.28843 16.8443 4.17373C17.1212 4.05903 17.418 4 17.7177 4C18.0174 4 18.3142 4.05903 18.5911 4.17373C18.868 4.28843 19.1196 4.45654 19.3315 4.66848C19.5435 4.88041 19.7116 5.13201 19.8263 5.40891C19.941 5.68582 20 5.9826 20 6.28232C20 6.58204 19.941 6.87882 19.8263 7.15573C19.7116 7.43263 19.5435 7.68423 19.3315 7.89617L8.43807 18.7896L4 20L5.21038 15.5619L16.1038 4.66848Z"
|
||||
stroke={themeMode=== "dark" ? "#F1F1F1" : "#333"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</IconButton>
|
||||
{data.defined ? (
|
||||
<Tooltip
|
||||
@@ -1151,7 +1164,7 @@ const AppAuthTab = memo((props) => {
|
||||
editAuthenticationConfig(data.id);
|
||||
}}
|
||||
>
|
||||
<SelectAllIcon color="secondary" />
|
||||
<SelectAllIcon color="textSecondary" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
) : (
|
||||
@@ -1439,6 +1452,9 @@ const SearchBox = ({ currentRefinement, refine, isSearchStalled, searchQuery, se
|
||||
refine(searchQuery.trim());
|
||||
};
|
||||
|
||||
const { themeMode, supportEmail } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
return (
|
||||
<form noValidate action="" role="search">
|
||||
<TextField
|
||||
@@ -1452,7 +1468,7 @@ const SearchBox = ({ currentRefinement, refine, isSearchStalled, searchQuery, se
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: "1em",
|
||||
height: 50,
|
||||
borderRadius: 4,
|
||||
@@ -1468,7 +1484,7 @@ const SearchBox = ({ currentRefinement, refine, isSearchStalled, searchQuery, se
|
||||
{searchQuery?.length > 0 && (
|
||||
<ClearIcon
|
||||
style={{
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
cursor: "pointer",
|
||||
marginRight: 10
|
||||
}}
|
||||
@@ -1485,7 +1501,7 @@ const SearchBox = ({ currentRefinement, refine, isSearchStalled, searchQuery, se
|
||||
style={{
|
||||
backgroundImage:
|
||||
"linear-gradient(to right, rgb(248, 106, 62), rgb(243, 64, 121))",
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
border: "none",
|
||||
padding: "10px 20px",
|
||||
width: 100,
|
||||
@@ -1523,8 +1539,6 @@ const SearchBox = ({ currentRefinement, refine, isSearchStalled, searchQuery, se
|
||||
|
||||
const Hits = ({
|
||||
hits,
|
||||
insights,
|
||||
setIsAnyAppActivated,
|
||||
searchQuery,
|
||||
isCloud,
|
||||
globalUrl,
|
||||
@@ -1548,6 +1562,8 @@ const Hits = ({
|
||||
}
|
||||
)
|
||||
const navigate = useNavigate();
|
||||
const { themeMode, supportEmail } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
const normalizedString = (name) => {
|
||||
if (typeof name === 'string') {
|
||||
@@ -1732,7 +1748,7 @@ const Hits = ({
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
toast.error("Failed to get app data or App doesn't. Please contact support@shuffler.io");
|
||||
toast.error(`Failed to get app data or App doesn't. Please contact ${supportEmail}`);
|
||||
return;
|
||||
}
|
||||
return response.json();
|
||||
@@ -1950,7 +1966,7 @@ const Hits = ({
|
||||
return (
|
||||
<div>
|
||||
<DialogTitle id="draggable-dialog-title" style={{ cursor: "move", }}>
|
||||
<div style={{ color: "white" }}>
|
||||
<div style={{ color: theme.palette.textColor }}>
|
||||
Authentication for {selectedApp.name.replaceAll("_", " ", -1)}
|
||||
</div>
|
||||
</DialogTitle>
|
||||
@@ -2020,7 +2036,7 @@ const Hits = ({
|
||||
}}
|
||||
style={{
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
height: 50,
|
||||
}}
|
||||
>
|
||||
@@ -2028,7 +2044,7 @@ const Hits = ({
|
||||
key={"false"}
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
}}
|
||||
value={"false"}
|
||||
>
|
||||
@@ -2038,7 +2054,7 @@ const Hits = ({
|
||||
key={"true"}
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
}}
|
||||
value={"true"}
|
||||
>
|
||||
@@ -2117,7 +2133,7 @@ const Hits = ({
|
||||
PaperProps={{
|
||||
style: {
|
||||
pointerEvents: "auto",
|
||||
color: "white",
|
||||
color: theme.palette.textColor,
|
||||
minWidth: 1100,
|
||||
minHeight: 700,
|
||||
maxHeight: 700,
|
||||
@@ -2399,7 +2415,7 @@ const Hits = ({
|
||||
href={selectedMeta.link}
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
>
|
||||
<Button style={{ color: "white", }} variant="outlined" color="secondary">
|
||||
<Button style={{ color: theme.palette.textColor, }} variant="outlined" color="secondary">
|
||||
<EditIcon /> Edit
|
||||
</Button>
|
||||
</a>
|
||||
@@ -2410,7 +2426,7 @@ const Hits = ({
|
||||
style={{
|
||||
height: "100%",
|
||||
width: 1,
|
||||
backgroundColor: "white",
|
||||
backgroundColor: theme.palette.textColor,
|
||||
marginLeft: 50,
|
||||
marginRight: 50,
|
||||
}}
|
||||
@@ -2505,7 +2521,7 @@ const Hits = ({
|
||||
height: 480,
|
||||
overflowY: "auto",
|
||||
scrollbarWidth: "thin",
|
||||
scrollbarColor: "#494949 #2f2f2f",
|
||||
scrollbarColor: theme.palette.scrollbarColor,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
@@ -2536,7 +2552,7 @@ const Hits = ({
|
||||
elevation={0}
|
||||
style={{
|
||||
...paperStyle,
|
||||
backgroundColor: mouseHoverIndex === index ? "#2F2F2F" : "rgba(26, 26, 26, 1)",
|
||||
backgroundColor: mouseHoverIndex === index ? theme.palette.cardHoverColor : theme.palette.cardBackgroundColor,
|
||||
width: "100%",
|
||||
}}
|
||||
onMouseEnter={() => setMouseHoverIndex(index)}
|
||||
@@ -2595,7 +2611,7 @@ const Hits = ({
|
||||
gap: 8,
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
color: "#F1F1F1",
|
||||
color: theme.palette.textColor,
|
||||
}}
|
||||
>
|
||||
{normalizedString(data.name)}
|
||||
@@ -2638,7 +2654,7 @@ const Hits = ({
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<Button style={{position: 'relative', borderRadius: 6, bottom: 10, marginRight: 10, fontSize: 16, backgroundColor: '#ff8544', color: "#1a1a1a", textTransform:'none', marginLeft: 'auto'}} onClick={(e)=> {e.preventDefault();e.stopPropagation();handleAppAuthenticationNew(data)()}}>
|
||||
<Button variant='contained' color='primary' style={{position: 'relative', borderRadius: 6, bottom: 10, marginRight: 10, fontSize: 16, textTransform:'none', marginLeft: 'auto'}} onClick={(e)=> {e.preventDefault();e.stopPropagation();handleAppAuthenticationNew(data)()}}>
|
||||
Authenticate app
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -42,9 +42,8 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
|
||||
const parsedStyle = {
|
||||
flex: 1,
|
||||
padding: 20,
|
||||
padding: "30px 20px 20px",
|
||||
margin: 12,
|
||||
paddingTop: 30,
|
||||
backgroundColor: hover && !makeFancy ? theme.palette.surfaceColor : "transparent",
|
||||
cursor: hover ? "pointer" : "default",
|
||||
textAlign: "center",
|
||||
@@ -346,23 +345,23 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
// Common dialog styles
|
||||
const dialogStyle = {
|
||||
borderRadius: 2,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.DialogStyle.border,
|
||||
minWidth: '500px',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
backgroundColor: "#1A1A1A",
|
||||
backgroundColor: theme.palette.DialogStyle.backgroundColor,
|
||||
zIndex: 1000,
|
||||
'& .MuiDialogContent-root': {
|
||||
backgroundColor: "#1A1A1A",
|
||||
backgroundColor: theme.palette.DialogStyle.backgroundColor,
|
||||
padding: '24px',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
},
|
||||
'& .MuiDialogTitle-root': {
|
||||
backgroundColor: "#1A1A1A",
|
||||
backgroundColor: theme.palette.DialogStyle.backgroundColor,
|
||||
padding: '24px',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
},
|
||||
'& .MuiDialogActions-root': {
|
||||
backgroundColor: "#1A1A1A",
|
||||
backgroundColor: theme.palette.DialogStyle.backgroundColor,
|
||||
padding: '16px 24px',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
},
|
||||
@@ -397,7 +396,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
pl: 4,
|
||||
pr: 3,
|
||||
}}>
|
||||
<Typography variant="h5" sx={{ fontWeight: 500, color: "#F1F1F1" }}>
|
||||
<Typography variant="h5"color="textPrimary" sx={{ fontWeight: 500, }}>
|
||||
Create New App
|
||||
</Typography>
|
||||
<IconButton
|
||||
@@ -409,8 +408,8 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
onClose()
|
||||
}}
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
'&:hover': { bgcolor: 'rgba(255, 255, 255, 0.1)' }
|
||||
color: theme.palette.text.primary,
|
||||
'&:hover': { bgcolor: theme.palette.hoverColor },
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
@@ -477,7 +476,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
px: 4,
|
||||
}}>
|
||||
<Typography variant="h6" sx={{
|
||||
color: '#F1F1F1',
|
||||
color: theme.palette.text.primary,
|
||||
fontWeight: 500,
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
}}>
|
||||
@@ -502,7 +501,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ px: 4, py: 3 }}>
|
||||
<div style={{ display: "flex", fontSize: '14px', gap: '5px', alignItems: 'center', marginBottom: '10px', fontFamily: theme?.typography?.fontFamily, marginTop: '15px' }}>
|
||||
<Typography sx={{ color: 'rgba(255,255,255,0.85)', fontSize: '16px' }}>
|
||||
<Typography sx={{ color: theme.palette.text.primary, fontSize: '16px' }}>
|
||||
Paste in the URI for the OpenAPI or find out
|
||||
</Typography>
|
||||
<Link style={{
|
||||
@@ -583,6 +582,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
py: 1,
|
||||
'&:hover': {
|
||||
borderColor: '#FF8544',
|
||||
color: '#FF8544',
|
||||
bgcolor: 'rgba(255,133,68,0.1)'
|
||||
},
|
||||
textTransform: 'none',
|
||||
@@ -665,7 +665,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
px: 4,
|
||||
}}>
|
||||
<Typography variant="h6" sx={{
|
||||
color: '#F1F1F1',
|
||||
color: theme.palette.text.primary,
|
||||
fontWeight: 500,
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
}}>
|
||||
@@ -681,8 +681,8 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
setValidation(false)
|
||||
}}
|
||||
sx={{
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
'&:hover': { bgcolor: 'rgba(255,255,255,0.1)' }
|
||||
color: theme.palette.text.primary,
|
||||
'&:hover': { bgcolor: theme.palette.hoverColor }
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
@@ -690,7 +690,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ px: 4, py: 3, pt: 0 }}>
|
||||
<Typography sx={{
|
||||
color: 'rgba(255,255,255,0.85)',
|
||||
color: theme.palette.text.primary,
|
||||
mb: 2,
|
||||
fontSize: '14px',
|
||||
mt: 2,
|
||||
@@ -706,10 +706,10 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
variant="outlined"
|
||||
placeholder="API Documentation URL"
|
||||
sx={{
|
||||
bgcolor: theme.palette.platformColor,
|
||||
bgcolor: theme.palette.textFieldStyle.backgroundColor,
|
||||
'& .MuiOutlinedInput-root': {
|
||||
height: '40px',
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
'& fieldset': {
|
||||
borderWidth: '1px',
|
||||
borderImage: "linear-gradient(to right, #ff8544 0%, #ec517c 50%, #9c5af2 100%) 1",
|
||||
@@ -757,7 +757,7 @@ const AppCreationModal = ({ open, onClose, theme, globalUrl, isCloud }) => {
|
||||
{circularLoader}
|
||||
{
|
||||
!validation &&
|
||||
<Typography sx={{ color: '#c5c5c5', fontSize: '14px', fontFamily: theme?.typography?.fontFamily, }}>
|
||||
<Typography color="textSecondary" sx={{ fontSize: '14px', fontFamily: theme?.typography?.fontFamily, }}>
|
||||
This may take multiple minutes based on the size of the documentation.
|
||||
</Typography>
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { memo, useCallback, useEffect, useState } from 'react';
|
||||
import React, { memo, useCallback, useEffect, useState, useContext } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
import {
|
||||
@@ -25,12 +25,13 @@ import LaunchIcon from '@mui/icons-material/Launch';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import { CloudDownloadOutlined, Delete } from '@mui/icons-material';
|
||||
import { findSpecificApp } from '../components/AppFramework.jsx';
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import YAML from 'yaml';
|
||||
import { toast } from 'react-toastify';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { InstantSearch, connectHits, connectSearchBox } from 'react-instantsearch-dom';
|
||||
import algoliasearch from "algoliasearch/lite";
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
|
||||
const searchClient = algoliasearch(
|
||||
"JNSS5CFDZZ",
|
||||
@@ -51,6 +52,9 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
const [deleteModalOpen, setDeleteModalOpen] = useState(false)
|
||||
const [sharingConfiguration, setSharingConfiguration] = React.useState("you");
|
||||
const navigate = useNavigate();
|
||||
const {themeMode} = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
const parseUsecase = (subcase) => {
|
||||
const srcdata = findSpecificApp(frameworkData, subcase.type)
|
||||
const dstdata = findSpecificApp(frameworkData, subcase.last)
|
||||
@@ -516,12 +520,12 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
border: "1px solid #494949",
|
||||
minWidth: '440px',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
'& .MuiDialogContent-root': {
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.DialogStyle.backgroundColor,
|
||||
},
|
||||
'& .MuiDialogTitle-root': {
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.DialogStyle.backgroundColor,
|
||||
},
|
||||
'& .MuiTypography-root': {
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
@@ -553,7 +557,7 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
<IconButton
|
||||
onClick={onClose}
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
color: theme.palette.textColor,
|
||||
'&:hover': { bgcolor: 'rgba(255, 255, 255, 0.1)' }
|
||||
}}
|
||||
style={{
|
||||
@@ -633,16 +637,14 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
sx={{
|
||||
bgcolor: '#494949',
|
||||
'&:hover': { bgcolor: '#494949' },
|
||||
textTransform: 'none',
|
||||
borderRadius: 1,
|
||||
minWidth: '45px',
|
||||
width: '45px',
|
||||
height: '40px',
|
||||
padding: 2,
|
||||
color: "#fff",
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
}}
|
||||
onClick={(event) => {
|
||||
@@ -658,19 +660,16 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
{(userdata?.id === app?.owner)? (
|
||||
<Tooltip title={"Delete app (confirm box will show)"}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
variant="contained"
|
||||
component="label"
|
||||
color="primary"
|
||||
color="secondary"
|
||||
sx={{
|
||||
bgcolor: '#494949',
|
||||
'&:hover': { bgcolor: '#494949', border: 'none' },
|
||||
textTransform: 'none',
|
||||
borderRadius: 1,
|
||||
minWidth: '45px',
|
||||
width: '45px',
|
||||
height: '40px',
|
||||
padding: 2,
|
||||
color: "#fff",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
border: 'none'
|
||||
}}
|
||||
@@ -687,15 +686,13 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
{(canEditApp && app?.generated) && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
sx={{
|
||||
bgcolor: "#494949",
|
||||
'&:hover': { bgcolor: '#494949' },
|
||||
textTransform: 'none',
|
||||
borderRadius: 1,
|
||||
py: 1,
|
||||
px: 3,
|
||||
height: '40px',
|
||||
color: "#fff",
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
}}
|
||||
startIcon={canEditApp ? <EditIcon /> : <ForkRightIcon />}
|
||||
@@ -729,7 +726,7 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
color: theme.palette.textColor,
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontSize: '14px'
|
||||
}}
|
||||
@@ -740,7 +737,7 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
<div style={{
|
||||
flex: 1,
|
||||
textAlign: "start",
|
||||
borderLeft: "1px solid rgba(255, 255, 255, 0.12)",
|
||||
borderLeft: theme.palette.defaultBorder,
|
||||
paddingLeft: "10px",
|
||||
height: "100%",
|
||||
}}>
|
||||
@@ -752,7 +749,7 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
}}>
|
||||
{Array.isArray(app?.actions) ? app.actions.length : app?.actions}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255, 255, 255, 0.7)' }}>
|
||||
<Typography variant="body2" sx={{ color: theme.palette.textColor }}>
|
||||
Actions
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -762,14 +759,14 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
paddingLeft: "10px",
|
||||
paddingTop: "5px"
|
||||
}}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '4px', marginBottom: "5px", fontFamily: theme?.typography?.fontFamily, fontSize: "14px", fontWeight: 600, color: 'white' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '4px', marginBottom: "5px", fontFamily: theme?.typography?.fontFamily, fontSize: "14px", fontWeight: 600, color: theme.palette.text.primary }}>
|
||||
{
|
||||
app?.collection ? (
|
||||
<>
|
||||
<CheckCircleIcon sx={{ color: '#4CAF50' }} />
|
||||
<Typography variant="body1" sx={{
|
||||
fontWeight: 500,
|
||||
color: '#fff',
|
||||
color: theme.palette.textColor,
|
||||
marginTop: "1px",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontSize: "16px"
|
||||
@@ -783,7 +780,7 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
fontSize: "16px",
|
||||
fontWeight: 500,
|
||||
marginTop: "1px",
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
color: theme.palette.textColor,
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
}}>
|
||||
No collection yet
|
||||
@@ -832,7 +829,7 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
)}
|
||||
|
||||
<Box sx={{
|
||||
bgcolor: '#2F2F2F',
|
||||
bgcolor: themeMode === "dark" ? "#1E1E1E" : "#F5F5F5",
|
||||
p: 2,
|
||||
borderRadius: 2,
|
||||
display: 'flex',
|
||||
@@ -895,16 +892,14 @@ const AppModal = ({ open, onClose, app, globalUrl, getApps}) => {
|
||||
<div style={{ display: "flex", justifyContent: "center", fontFamily: theme?.typography?.fontFamily }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
sx={{
|
||||
bgcolor: '#FF8544',
|
||||
'&:hover': { bgcolor: '#FF8544' },
|
||||
textTransform: 'none',
|
||||
borderRadius: "4px",
|
||||
py: 1,
|
||||
px: 7,
|
||||
fontSize: "14px",
|
||||
letterSpacing: "0.5px",
|
||||
color: "black",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
minWidth: '200px'
|
||||
}}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import theme from '../theme.jsx';
|
||||
import React, { useState, useEffect, useRef, useContext } from "react";
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import ReactGA from 'react-ga4';
|
||||
import { useNavigate, Link } from 'react-router-dom';
|
||||
import { isMobile } from 'react-device-detect';
|
||||
@@ -36,9 +36,12 @@ import {
|
||||
IconButton,
|
||||
} from '@mui/material';
|
||||
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
const AppSearchButtons = (props) => {
|
||||
const { userdata, globalUrl, appFramework, moreButton, finishedApps, appType, totalApps, index, onNodeSelect, setDiscoveryData, appName, AppImage, setDefaultSearch, discoveryData, checkLogin, setMissing, getAppFramework, } = props
|
||||
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
const ref = useRef()
|
||||
let navigate = useNavigate();
|
||||
|
||||
@@ -195,13 +198,13 @@ const AppSearchButtons = (props) => {
|
||||
zIndex: 100,
|
||||
borderRadius: 6,
|
||||
border: "1px solid var(--Container-Stroke, #494949)",
|
||||
background: "var(--Container, #212121)",
|
||||
background: theme.palette.platformColor,
|
||||
boxShadow: "8px 8px 32px 24px rgba(0, 0, 0, 0.16)",
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "flex" }}>
|
||||
<div style={{ display: "flex", textAlign: "center", textTransform: "capitalize" }}>
|
||||
<Typography style={{ padding: 16, color: "#FFFFFF", textTransform: "capitalize" }}> {discoveryData} </Typography>
|
||||
<Typography color="textPrimary" style={{ padding: 16, textTransform: "capitalize" }}> {discoveryData} </Typography>
|
||||
</div>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Tooltip
|
||||
@@ -288,17 +291,17 @@ const AppSearchButtons = (props) => {
|
||||
</div>
|
||||
) : null}
|
||||
<div style={{
|
||||
display: "flex", height: 70, border: isHover ? "1px solid #f85a3e" : "var(--Container, #212121)", borderRadius: 8, background: isHover ? "var(--Container, #212121)" : "var(--Container, #212121)",
|
||||
display: "flex", height: 70, border: isHover ? "1px solid #f85a3e" : "var(--Container, #212121)", borderRadius: 4, background: isHover ? "var(--Container, #212121)" : "var(--Container, #212121)",
|
||||
alignItems: "center", justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
fullWidth
|
||||
color="secondary"
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
display: "grid"
|
||||
display: "grid",
|
||||
backgroundColor: themeMode === "dark" ? "#212121" : "#F5F5F5",
|
||||
}}
|
||||
onClick={(event) => {
|
||||
if (onNodeSelect !== undefined) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
|
||||
import classNames from "classnames";
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
|
||||
import {
|
||||
Tooltip,
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
Chip,
|
||||
Checkbox,
|
||||
} from "@mui/material";
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
|
||||
import {
|
||||
BarChart,
|
||||
@@ -73,6 +74,8 @@ const inputdata = {
|
||||
|
||||
const LineChartWrapper = ({keys, inputname, height, width}) => {
|
||||
const [hovered, setHovered] = useState("");
|
||||
const {themeMode} = useContext(Context);
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
//console.log("Date: ", new Date("2019-11-14T08:00:00.000Z"))
|
||||
//var inputdata = keys.data
|
||||
@@ -166,6 +169,8 @@ const AppStats = (defaultprops) => {
|
||||
const [searches, setSearches] = useState([]);
|
||||
const [clickData, setClickData] = useState(undefined);
|
||||
const [conversionData, setConversionData] = useState(undefined);
|
||||
const {themeMode} = useContext(Context);
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const handleDataSetting = (inputdata, grouping) => {
|
||||
var newlist = []
|
||||
@@ -292,7 +297,7 @@ const AppStats = (defaultprops) => {
|
||||
textAlign: "center",
|
||||
padding: 40,
|
||||
margin: 5,
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
}
|
||||
|
||||
console.log("Widget: ", widgetData)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
import ReactGA from 'react-ga4';
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import {Link} from 'react-router-dom';
|
||||
import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@mui/icons-material';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
//import algoliasearch from 'algoliasearch/lite';
|
||||
import algoliasearch from 'algoliasearch';
|
||||
import { InstantSearch, connectSearchBox, connectHits } from 'react-instantsearch-dom';
|
||||
@@ -23,7 +23,8 @@ import aa from 'search-insights'
|
||||
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240")
|
||||
const Appsearch = props => {
|
||||
const { maxRows, showName, showSuggestion, isMobile, globalUrl, parsedXs, newSelectedApp, setNewSelectedApp, defaultSearch, showSearch, ConfiguredHits, userdata, cy, isCreatorPage, actionImageList, setActionImageList, setUserSpecialzedApp } = props
|
||||
|
||||
const { themeMode } = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
const isCloud = (window.location.host === "localhost:3002" || window.location.host === "shuffler.io") ? true : (process.env.IS_SSR === "true");
|
||||
const rowHandler = maxRows === undefined || maxRows === null ? 50 : maxRows
|
||||
const xs = parsedXs === undefined || parsedXs === null ? 12 : parsedXs
|
||||
@@ -54,10 +55,10 @@ const Appsearch = props => {
|
||||
autoComplete="off"
|
||||
autocomplete="off"
|
||||
fullWidth
|
||||
style={{backgroundColor: "#2F2F2F", borderRadius: borderRadius, width: "100%",}}
|
||||
style={{backgroundColor: theme.palette.textFieldStyle.backgroundColor, borderRadius: borderRadius, width: "100%",}}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: "1em",
|
||||
height: 50,
|
||||
},
|
||||
@@ -93,7 +94,7 @@ const Appsearch = props => {
|
||||
<Grid container spacing={0} style={{border: "1px solid rgba(255,255,255,0.2)", maxHeight: 250, minHeight: 250, overflowY: "auto", overflowX: "hidden", }}>
|
||||
{hits.map((data, index) => {
|
||||
const paperStyle = {
|
||||
backgroundColor: index === mouseHoverIndex ? "rgba(255,255,255,0.8)" : "#2F2F2F",
|
||||
backgroundColor: index === mouseHoverIndex ? theme.palette.hoverColor : theme.palette.textFieldStyle.backgroundColor,
|
||||
color: index === mouseHoverIndex ? theme.palette.inputColor : "rgba(255,255,255,0.8)",
|
||||
// border: newSelectedApp.objectID !== data.objectID ? `1px solid rgba(255,255,255,0.2)` : "2px solid #f86a3e",
|
||||
textAlign: "left",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React, { useState, useEffect, useContext, memo, useMemo } from "react";
|
||||
import React, { useState, useEffect, memo, useMemo, useContext } from "react";
|
||||
import ReactGA from 'react-ga4';
|
||||
|
||||
import theme from "../theme.jsx";
|
||||
import { getTheme } from "../theme.jsx";
|
||||
import countries from "../components/Countries.jsx";
|
||||
|
||||
import {
|
||||
Box,
|
||||
Paper,
|
||||
@@ -26,7 +26,10 @@ import {
|
||||
DialogContentText,
|
||||
DialogActions,
|
||||
LinearProgress,
|
||||
Slider
|
||||
Slider,
|
||||
Tabs,
|
||||
Tab,
|
||||
CircularProgress,
|
||||
} from "@mui/material";
|
||||
|
||||
import { useNavigate, Link, json } from "react-router-dom";
|
||||
@@ -43,6 +46,8 @@ import {
|
||||
Cloud,
|
||||
CheckCircle,
|
||||
Padding,
|
||||
Edit,
|
||||
Search as SearchIcon
|
||||
} from "@mui/icons-material";
|
||||
|
||||
//import { useAlert
|
||||
@@ -52,11 +57,14 @@ import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import LicencePopup from "./LicencePopup.jsx";
|
||||
import { DataGrid } from "@mui/x-data-grid";
|
||||
|
||||
const Billing = memo((props) => {
|
||||
const { globalUrl, userdata, serverside, billingInfo, stripeKey,isLoaded, selectedOrganization, handleGetOrg, clickedFromOrgTab, removeCookie} = props;
|
||||
//const alert = useAlert();
|
||||
let navigate = useNavigate();
|
||||
const { themeMode, brandColor,supportEmail } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
const [isLoggedIn, setIsLoggedIn] = useState(false)
|
||||
const [selectedDealModalOpen, setSelectedDealModalOpen] = React.useState(false);
|
||||
const [dealList, setDealList] = React.useState([]);
|
||||
@@ -78,6 +86,9 @@ const Billing = memo((props) => {
|
||||
const [deleteAlertIndex, setDeleteAlertIndex] = useState(-1);
|
||||
const [deleteAlertVerification, setDeleteAlertVerification] = useState(false);
|
||||
const [isScale, setIsScale] = useState(false);
|
||||
const [currentTab, setCurrentTab] = useState(0)
|
||||
const [allChildOrgs, setAllChildOrgs] = useState([])
|
||||
const [allChildOrgsStats, setAllChildOrgsStats] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
if (userdata.app_execution_limit !== undefined && userdata.app_execution_usage !== undefined) {
|
||||
@@ -85,6 +96,7 @@ const Billing = memo((props) => {
|
||||
setCurrentAppRunsInPercentage(Math.round(percentage));
|
||||
setCurrentAppRunsInNumber(userdata.app_execution_limit - userdata.app_execution_usage);
|
||||
}
|
||||
|
||||
if (userdata?.id?.length > 0 && isLoggedIn === false){
|
||||
setIsLoggedIn(true)
|
||||
}
|
||||
@@ -92,6 +104,17 @@ const Billing = memo((props) => {
|
||||
|
||||
const [BillingEmail, setBillingEmail] = useState(selectedOrganization?.Billing?.Email);
|
||||
|
||||
useEffect(() => {
|
||||
const urlIncludesProfessionalServices = window.location.href.includes("professional-services");
|
||||
if (props?.isCloud && urlIncludesProfessionalServices) {
|
||||
const professionalServicesSection =
|
||||
document.getElementById("professional-services");
|
||||
if (professionalServicesSection) {
|
||||
professionalServicesSection.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (BillingEmail !== selectedOrganization?.Billing?.Email) {
|
||||
setBillingEmail(selectedOrganization?.Billing?.Email);
|
||||
@@ -337,6 +360,7 @@ const Billing = memo((props) => {
|
||||
const [tosChecked, setTosChecked] = React.useState(subscription.eula_signed)
|
||||
const [hovered, setHovered] = React.useState(false)
|
||||
const [newBillingEmail, setNewBillingEmail] = useState('');
|
||||
const {supportEmail} = useContext(Context);
|
||||
|
||||
var top_text = "Base Cloud Access"
|
||||
if (subscription.limit === undefined && subscription.level === undefined || subscription.level === null || subscription.level === 0) {
|
||||
@@ -537,7 +561,7 @@ const Billing = memo((props) => {
|
||||
Accept
|
||||
</Typography>
|
||||
<Typography variant="body2" style={{ display: "inline-block", marginLeft: 10, }} color="textSecondary">
|
||||
By clicking the “accept” button, you are signing the document, electronically agreeing that it has the same legal validity and effects as a handwritten signature, and that you have the competent authority to represent and sign on behalf an entity. Need support or have questions? Contact us at support@shuffler.io.
|
||||
By clicking the “accept” button, you are signing the document, electronically agreeing that it has the same legal validity and effects as a handwritten signature, and that you have the competent authority to represent and sign on behalf an entity. Need support or have questions? Contact us at {supportEmail}
|
||||
</Typography>
|
||||
|
||||
<div style={{ display: "flex", marginTop: 25, }}>
|
||||
@@ -1066,8 +1090,8 @@ const Billing = memo((props) => {
|
||||
padding: 20,
|
||||
// maxWidth: 400,
|
||||
width: "100%",
|
||||
height: 480,
|
||||
backgroundColor: hovered ? "#2b2b2b" : "#1e1e1e",
|
||||
height: 500,
|
||||
backgroundColor: hovered ? theme.palette.cardHoverColor : theme.palette.cardBackgroundColor,
|
||||
borderRadius: theme.palette?.borderRadius * 2,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
marginRight: 10,
|
||||
@@ -1138,12 +1162,12 @@ const Billing = memo((props) => {
|
||||
Features
|
||||
</Typography>
|
||||
<ul>
|
||||
<li>
|
||||
<li style={{color : theme.palette.text.primary}}>
|
||||
<Typography variant="body2" color="textPrimary" style={{}}>
|
||||
Build custom apps, integrations, and worklows for your specific use cases or applications
|
||||
</Typography>
|
||||
</li>
|
||||
<li>
|
||||
<li style={{color : theme.palette.text.primary}}>
|
||||
<Typography variant="body2" color="textPrimary" style={{}}>
|
||||
Help solve / debug / update / add features and capabilities of the platform
|
||||
</Typography>
|
||||
@@ -1154,15 +1178,13 @@ const Billing = memo((props) => {
|
||||
<Button
|
||||
fullWidth
|
||||
disabled={false}
|
||||
variant="outlined"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
marginTop: userdata.support ? 0 : 10,
|
||||
marginTop: userdata.support ? 3 : 15,
|
||||
borderRadius: 4,
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
color: "#1A1A1A",
|
||||
backgroundColor: "#FF8544",
|
||||
textTransform: 'none',
|
||||
}}
|
||||
onClick={() => {
|
||||
@@ -1228,7 +1250,7 @@ const Billing = memo((props) => {
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
style={{
|
||||
marginTop: userdata.support ? 5 : 10,
|
||||
marginTop: userdata.support ? 10 : 15,
|
||||
borderRadius: 4,
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
@@ -1354,7 +1376,7 @@ const Billing = memo((props) => {
|
||||
toast.success("Your request for private training has been submitted successfully. We will get back to you soon.")
|
||||
setOpenPrivateTraining(false)
|
||||
} else {
|
||||
toast.error("Failed sending request for private training. Please try again later or contact support@shuffler.io for help.")
|
||||
toast.error(`Failed sending request for private training. Please try again later or contact support@shuffler.io for help.`)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1363,10 +1385,10 @@ const Billing = memo((props) => {
|
||||
<div
|
||||
style={{
|
||||
padding: 20,
|
||||
height: 480,
|
||||
height: 500,
|
||||
// maxWidth: 400,
|
||||
width: "100%",
|
||||
backgroundColor: hovered ? "#2b2b2b" : "#1e1e1e",
|
||||
backgroundColor: hovered ? theme.palette.cardHoverColor : theme.palette.cardBackgroundColor,
|
||||
borderRadius: theme.palette?.borderRadius * 2,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
marginRight: 10,
|
||||
@@ -1387,12 +1409,12 @@ const Billing = memo((props) => {
|
||||
Public Training
|
||||
</Typography>
|
||||
<ul>
|
||||
<li>
|
||||
<li style={{color : theme.palette.text.primary}}>
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
Public course on Automation for Security Professionals
|
||||
</Typography>
|
||||
</li>
|
||||
<li>
|
||||
<li style={{color : theme.palette.text.primary}}>
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
Covers Shuffle Platform, Apps, Workflows, Usecases, JSON, Liquid Formatting, and more.
|
||||
</Typography>
|
||||
@@ -1402,12 +1424,12 @@ const Billing = memo((props) => {
|
||||
Private Training
|
||||
</Typography>
|
||||
<ul>
|
||||
<li>
|
||||
<li style={{color : theme.palette.text.primary}}>
|
||||
<Typography variant="body2" color="textPrimary">
|
||||
Everything from Public Training
|
||||
</Typography>
|
||||
</li>
|
||||
<li>
|
||||
<li style={{color : theme.palette.text.primary}}>
|
||||
<Typography variant="body2" color="textPrimary" >
|
||||
Customized for your team’s usecases, date and time, location, and more.
|
||||
</Typography>
|
||||
@@ -1425,9 +1447,7 @@ const Billing = memo((props) => {
|
||||
borderRadius: 4,
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
color: "#1A1A1A",
|
||||
textTransform: 'none',
|
||||
backgroundColor: "#FF8544",
|
||||
width: "100%",
|
||||
}}
|
||||
onClick={() => {
|
||||
@@ -1971,16 +1991,18 @@ const Billing = memo((props) => {
|
||||
<div style={{ width: "100%",}}>
|
||||
{addDealModal}
|
||||
{clickedFromOrgTab ?
|
||||
<Typography style={{fontSize: 24, fontWeight: "bold", marginBottom: 8, marginTop: 0, color: "#ffffff" }}>Billing & Licensing</Typography> :
|
||||
<Typography variant="h5" style={{fontSize: 24, fontWeight: 500, marginBottom: 8, marginTop: 0, }}>Billing & Licensing</Typography> :
|
||||
<Typography variant="h4" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||
Billing & Licensing
|
||||
</Typography>}
|
||||
{userdata?.org_status?.includes("integration_partner") && userdata?.org_status?.includes("sub_org") ? null :
|
||||
<>
|
||||
{clickedFromOrgTab ?
|
||||
<span style={{ color: "#9E9E9E", fontSize: 16 }}>{isCloud ?
|
||||
<Typography variant="body2" color="textSecondary" style={{ fontSize: 16 }}>{isCloud ?
|
||||
"Get more out of Shuffle by adding your credit card, such as no App Run limitations, and priority support from our team. We use Stripe to manage subscriptions and do not store any of your billing information. You can manage your subscription and billing information below."
|
||||
:
|
||||
"Shuffle is an Open Source automation platform, and no license is required. We do however offer a Scale license with HA guarantees, along with support hours. By buying a license on https://shuffler.io, you can get access to the license immediately, and if Cloud Syncronisation is enabled, the UI in your local instance will also update."
|
||||
}</span> :
|
||||
}</Typography> :
|
||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 0, marginBottom: 10, fontSize: 16 }}>
|
||||
{isCloud ?
|
||||
"Get more out of Shuffle by adding your credit card, such as no App Run limitations, and priority support from our team. We use Stripe to manage subscriptions and do not store any of your billing information. You can manage your subscription and billing information below."
|
||||
@@ -1988,9 +2010,10 @@ const Billing = memo((props) => {
|
||||
"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."
|
||||
}
|
||||
</Typography>}
|
||||
</> }
|
||||
|
||||
{userdata.support === true ?
|
||||
<div style={{ marginBottom: 10, marginTop: clickedFromOrgTab ? 16 : null, color: clickedFromOrgTab ? "#F1F1F1" : null }}>
|
||||
<Typography style={{ marginBottom: 10, marginTop: clickedFromOrgTab ? 16 : null, color: clickedFromOrgTab ? theme.palette.text.primary : null }}>
|
||||
For sales: Create
|
||||
<a href={"https://docs.google.com/document/d/1N-ZJNn8lWaqiXITrqYcnTt53oXGLNYFEzc5PU-tdAps/copy"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#FF8444" }}>
|
||||
EU contract
|
||||
@@ -2007,7 +2030,7 @@ const Billing = memo((props) => {
|
||||
<a href={"https://github.com/Shuffle/Shuffle-docs/tree/master/handbook/Sales"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#FF8444" }}>
|
||||
Sales Process (old)
|
||||
</a>
|
||||
</div>
|
||||
</Typography>
|
||||
:
|
||||
null
|
||||
}
|
||||
@@ -2015,11 +2038,11 @@ const Billing = memo((props) => {
|
||||
|
||||
{isChildOrg ?
|
||||
<Typography variant="h6" style={{ marginBottom: 50, }}>
|
||||
Licensing is handled by your parent organisation. Reach out to support@shuffler.io if you have questions about this.
|
||||
Licensing is handled by your parent organisation. Reach out to {supportEmail} if you have questions about this.
|
||||
</Typography>
|
||||
: null}
|
||||
|
||||
<div style={{ display: "flex", width: clickedFromOrgTab ? "100%" : "auto", overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: '#494949 #2f2f2f', height: isChildOrg ? 0 : "100%", marginTop: 20}} >
|
||||
<div style={{ display: "flex", width: clickedFromOrgTab ? "100%" : "auto", overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: theme.palette.scrollbarColor, height: isChildOrg ? 0 : "100%", marginTop: 20}} >
|
||||
<div style={{ display: "flex", flexDirection: "column", width: "100%", }}>
|
||||
{/* {isCloud &&
|
||||
selectedOrganization.subscriptions !== undefined &&
|
||||
@@ -2354,13 +2377,13 @@ const Billing = memo((props) => {
|
||||
</div>
|
||||
) : null*/}
|
||||
{!isChildOrg && isCloud && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', marginTop: 50, maxWidth: 860 }}>
|
||||
<Typography style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', marginTop: 50, maxWidth: 860 }} id="professional-services">
|
||||
<Typography variant="h6" style={{ marginBottom: 5, fontSize: 24, fontWeight: 500 }}>
|
||||
Professional Services
|
||||
</Typography>
|
||||
<Typography color="textSecondary" style={{fontSize: 16,}}>
|
||||
We offer priority support through consultations and training to help you make the most of our product. If you have any questions, please reach out to us at support@shuffler.io.
|
||||
</Typography>
|
||||
<Typography variant="body2" 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 {supportEmail}.
|
||||
</Typography>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
|
||||
<div style={{ display: 'flex', flexDirection: 'row', marginTop: 5, }}>
|
||||
{billingInfo.subscription !== undefined && billingInfo.subscription !== null ? (
|
||||
isChildOrg ? null : (
|
||||
@@ -2426,14 +2449,16 @@ const Billing = memo((props) => {
|
||||
<TextField
|
||||
style={{
|
||||
marginTop: 10,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
borderRadius: theme.palette.textFieldStyle.borderRadius,
|
||||
width: 250,
|
||||
height: 50,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
height: 50,
|
||||
color: 'white',
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
endAdornment: '%',
|
||||
}}
|
||||
@@ -2456,14 +2481,16 @@ const Billing = memo((props) => {
|
||||
style={{
|
||||
marginTop: 10,
|
||||
height: 50,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
width: 250,
|
||||
marginLeft: 15,
|
||||
borderRadius: theme.palette.textFieldStyle.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
height: 50,
|
||||
color: 'white',
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
}}
|
||||
InputLabelProps={{
|
||||
@@ -2505,7 +2532,7 @@ const Billing = memo((props) => {
|
||||
setDeleteAlertIndex(index);
|
||||
}}
|
||||
>
|
||||
<DeleteIcon sx={{ color: theme.palette.secondary.main }} />
|
||||
<DeleteIcon sx={{ color: themeMode === "dark" ? "rgba(255,255,255,0.7)" : "#666666" }} />
|
||||
</Button>
|
||||
)}
|
||||
<Dialog
|
||||
@@ -2526,7 +2553,8 @@ const Billing = memo((props) => {
|
||||
</Button>
|
||||
<Button
|
||||
style={{ textTransform: 'none', fontSize: 16 }}
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
handleDeleteAlertThreshold(deleteAlertIndex);
|
||||
setDeleteAlertVerification(false);
|
||||
@@ -2569,6 +2597,41 @@ const Billing = memo((props) => {
|
||||
Utilization & Stats
|
||||
</Typography>
|
||||
</div>
|
||||
{isChildOrg ? (
|
||||
<BillingStats
|
||||
isCloud={isCloud}
|
||||
clickedFromOrgTab={clickedFromOrgTab}
|
||||
globalUrl={globalUrl}
|
||||
selectedOrganization={selectedOrganization}
|
||||
userdata={userdata}
|
||||
/>
|
||||
): (
|
||||
<>
|
||||
<Tabs
|
||||
value={currentTab}
|
||||
onChange={(event, newValue) => setCurrentTab(newValue)}
|
||||
style={{ marginTop: 20 }}
|
||||
TabIndicatorProps={{
|
||||
style: {
|
||||
height: 3,
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
marginLeft: 12,
|
||||
marginRight: 12,
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Tab
|
||||
label="Parent Organization"
|
||||
style={{ textTransform: 'none', fontSize: 16, minWidth: 'auto', paddingLeft: 12, paddingRight: 12 }}
|
||||
/>
|
||||
<Tab
|
||||
label="Child Organization"
|
||||
style={{ textTransform: 'none', fontSize: 16, minWidth: 'auto', paddingLeft: 12, paddingRight: 12 }}
|
||||
/>
|
||||
</Tabs>
|
||||
|
||||
{currentTab === 0 ? (
|
||||
<div style={{ marginTop: 30,}}>
|
||||
<BillingStats
|
||||
isCloud={isCloud}
|
||||
clickedFromOrgTab={clickedFromOrgTab}
|
||||
@@ -2577,25 +2640,495 @@ const Billing = memo((props) => {
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
): (
|
||||
<BillingStatsChildOrg
|
||||
isCloud={isCloud}
|
||||
clickedFromOrgTab={clickedFromOrgTab}
|
||||
globalUrl={globalUrl}
|
||||
selectedOrganization={selectedOrganization}
|
||||
userdata={userdata}
|
||||
allChildOrgs={allChildOrgs}
|
||||
setAllChildOrgs={setAllChildOrgs}
|
||||
allChildOrgsStats={allChildOrgsStats}
|
||||
setAllChildOrgsStats={setAllChildOrgsStats}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Wrapper>
|
||||
)
|
||||
})
|
||||
|
||||
export default memo(Billing);
|
||||
|
||||
const BillingStatsChildOrg = memo(({ userdata, globalUrl, selectedOrganization, allChildOrgs, setAllChildOrgs, allChildOrgsStats, setAllChildOrgsStats }) => {
|
||||
const [subOrgStats, setSubOrgStats] = useState([]);
|
||||
const [subOrgs, setSubOrgs] = useState([]);
|
||||
const [subOrgStatsRows, setSubOrgStatsRows] = useState([]);
|
||||
const [subOrgStatsColumns, setSubOrgStatsColumns] = useState([]);
|
||||
const [allOrgLoaded, setAllOrgLoaded] = useState(false);
|
||||
const [allOrgStatsLoaded, setAllOrgStatsLoaded] = useState(false);
|
||||
const [page, setPage] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [editing, setEditing] = useState("")
|
||||
const [editingOrgId, setEditingOrgId] = useState("")
|
||||
const [limit, setLimit] = useState("")
|
||||
const [tableCreated, setTableCreated] = useState(false)
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [filteredRows, setFilteredRows] = useState([]);
|
||||
const { themeMode, brandColor, supportEmail } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
// Handle page change
|
||||
const handleChangePage = (event, newPage) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const handleChangeRowsPerPage = (event) => {
|
||||
setRowsPerPage(parseInt(event.target.value, 10));
|
||||
setPage(0);
|
||||
};
|
||||
|
||||
const HanldeLoadStats = async () => {
|
||||
const childOrgs = selectedOrganization.child_orgs;
|
||||
if (allChildOrgsStats.length > 0){
|
||||
setSubOrgStats(allChildOrgsStats)
|
||||
setAllOrgStatsLoaded(true)
|
||||
if (allChildOrgsStats.length > 0 && allChildOrgs.length > 0 && subOrgStatsRows.length === 0 && subOrgStatsColumns.length === 0) {
|
||||
HandleCreateTable(allChildOrgsStats, allChildOrgs)
|
||||
}
|
||||
return
|
||||
}
|
||||
const promises = childOrgs.map((org) => {
|
||||
// get org stats base on region url
|
||||
const baseUrl = org?.region_url?.length > 0 && !window?.location?.origin?.includes("localhost") ? org?.region_url : globalUrl;
|
||||
const url = `${baseUrl}/api/v1/orgs/${org.id}/stats`;
|
||||
return fetch(url, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}).then((res) => res.json());
|
||||
});
|
||||
|
||||
try {
|
||||
const responses = await Promise.all(promises);
|
||||
setSubOrgStats(responses);
|
||||
setAllChildOrgsStats(responses);
|
||||
setAllOrgStatsLoaded(true);
|
||||
} catch (error) {
|
||||
console.error("Error loading stats:", error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const HandleGetSuborg = async () => {
|
||||
const childOrgs = selectedOrganization.child_orgs
|
||||
|
||||
if (allChildOrgs.length > 0){
|
||||
setSubOrgs(allChildOrgs)
|
||||
setAllOrgLoaded(true)
|
||||
if (allChildOrgsStats.length > 0 && allChildOrgs.length > 0 && subOrgStatsRows.length === 0 && subOrgStatsColumns.length === 0) {
|
||||
HandleCreateTable(allChildOrgsStats, allChildOrgs)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const promises = childOrgs.map((org) => {
|
||||
const baseUrl = org?.region_url?.length > 0 && !window?.location?.origin?.includes("localhost") ? org?.region_url : globalUrl;
|
||||
const url = `${baseUrl}/api/v1/orgs/${org.id}`;
|
||||
return fetch(url, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}).then((res) => res.json());
|
||||
});
|
||||
try {
|
||||
const responses = await Promise.all(promises);
|
||||
setSubOrgs(responses);
|
||||
setAllChildOrgs(responses);
|
||||
setAllOrgLoaded(true);
|
||||
} catch (error) {
|
||||
console.error("Error loading suborgs:", error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (subOrgStats.length === 0 && selectedOrganization && selectedOrganization?.child_orgs?.length > 0) {
|
||||
HanldeLoadStats()
|
||||
}
|
||||
if (subOrgs.length === 0 && selectedOrganization && selectedOrganization?.child_orgs?.length > 0) {
|
||||
HandleGetSuborg()
|
||||
}
|
||||
|
||||
}, [selectedOrganization?.child_orgs]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (allOrgLoaded && allOrgStatsLoaded && !tableCreated) {
|
||||
HandleCreateTable(subOrgStats, subOrgs)
|
||||
}
|
||||
}
|
||||
, [allOrgLoaded, allOrgStatsLoaded, tableCreated])
|
||||
|
||||
|
||||
const HandleCreateTable = (subOrgStats, subOrgs) => {
|
||||
|
||||
if (subOrgStats.length === 0 || subOrgs.length === 0) return;
|
||||
|
||||
// check whether all of the suborg.success is false
|
||||
const allSubOrgStatsSuccess = subOrgStats.every((stat) => stat.success === false);
|
||||
const allSubOrgsSuccess = subOrgs.every((org) => org.success === false);
|
||||
|
||||
if (allSubOrgStatsSuccess || allSubOrgsSuccess) {
|
||||
setSubOrgStats([])
|
||||
setSubOrgs([])
|
||||
setTableCreated(true)
|
||||
return
|
||||
}
|
||||
|
||||
const rows = subOrgStats.map((stat, index) => {
|
||||
const subOrg = subOrgs[index]
|
||||
if (!subOrg) return null;
|
||||
return {
|
||||
id: index,
|
||||
name: subOrg.name,
|
||||
orgId: subOrg.id,
|
||||
limit: subOrg?.sync_features?.app_executions?.limit || "N/A",
|
||||
usage: stat?.monthly_app_executions || "N/A",
|
||||
workflows_usage: stat?.total_workflow_executions || "N/A",
|
||||
workflow_usage_limit: subOrg?.sync_features?.workflow_executions?.limit || "N/A",
|
||||
}
|
||||
})
|
||||
|
||||
setSubOrgStatsRows(rows)
|
||||
|
||||
const columns = [
|
||||
{ field: "id", headerName: "ID", width: 100 },
|
||||
{ field: "name", headerName: "Name", width: 200 },
|
||||
{ field: "usage", headerName: "App Execution Usage", width: 200 },
|
||||
{
|
||||
field: "limit", headerName: "App Execution Limit", width: 200, renderCell: (params) => {
|
||||
return (
|
||||
<>
|
||||
<Typography style={{ fontSize: 16 }}>
|
||||
{params.value}
|
||||
<IconButton
|
||||
style={{ color: theme.palette.primary.main }}
|
||||
onClick={() => {
|
||||
setOpen(true)
|
||||
setEditingOrgId(params.row.orgId)
|
||||
setEditing("app_executions")
|
||||
if (params.value === "N/A") {
|
||||
setLimit("")
|
||||
} else {
|
||||
setLimit(params.value)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Edit/>
|
||||
</IconButton>
|
||||
</Typography>
|
||||
</>
|
||||
)
|
||||
}
|
||||
},
|
||||
{ field: "workflows_usage", headerName: "Workflow Execution Usage", width: 200 },
|
||||
{ field: "workflow_usage_limit", headerName: "Workflow Execution Limit", width: 200, renderCell: (params) => {
|
||||
return (
|
||||
<>
|
||||
<Typography style={{ fontSize: 16 }}>
|
||||
{params.value}
|
||||
</Typography>
|
||||
<IconButton
|
||||
style={{ color: theme.palette.primary.main }}
|
||||
onClick={() => {
|
||||
setOpen(true)
|
||||
setEditingOrgId(params.row.orgId)
|
||||
setEditing("workflow_executions")
|
||||
if (params.value === "N/A") {
|
||||
setLimit("")
|
||||
} else {
|
||||
setLimit(params.value)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Edit/>
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
},
|
||||
]
|
||||
|
||||
setSubOrgStatsColumns(columns)
|
||||
|
||||
if (allOrgLoaded && allOrgStatsLoaded && !tableCreated) {
|
||||
setTableCreated(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const HandleEditLimit = (orgId, editing, limit) => {
|
||||
|
||||
|
||||
// change limit as number if string
|
||||
if (typeof limit === "string") {
|
||||
limit = parseInt(limit, 10)
|
||||
}
|
||||
if (isNaN(limit)) {
|
||||
toast.error("Please enter a valid number")
|
||||
return
|
||||
}
|
||||
|
||||
if (selectedOrganization.sync_features.app_executions.limit <= 10000) {
|
||||
toast.error("Insufficient app execution limit to increase child org limit")
|
||||
return
|
||||
}
|
||||
|
||||
// check whether limit is greater than than parent org limit
|
||||
if (editing === "app_executions" && limit > selectedOrganization.sync_features.app_executions.limit && !userdata.support) {
|
||||
toast.error("App execution limit cannot be greater than parent org limit")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (editing === "workflow_executions" && limit > selectedOrganization.sync_features.workflow_executions.limit && !userdata.support) {
|
||||
toast.error("Workflow execution limit cannot be greater than parent org limit")
|
||||
return
|
||||
}
|
||||
|
||||
// find the org in the subOrgs array
|
||||
const orgIndex = subOrgs.findIndex((org) => org.id === orgId)
|
||||
if (orgIndex === -1) {
|
||||
toast.error("Organization not found")
|
||||
return
|
||||
}
|
||||
|
||||
const org = subOrgs[orgIndex]
|
||||
|
||||
org.sync_features[editing].limit = limit
|
||||
org.sync_features.editing = true
|
||||
const sync_features = org.sync_features
|
||||
const data = {
|
||||
org_id: orgId,
|
||||
sync_features: sync_features,
|
||||
}
|
||||
|
||||
const url = `${globalUrl}/api/v1/orgs/${orgId}`;
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
crossDomain: true,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
}).then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
if (responseJson["success"] === false) {
|
||||
toast("Failed updating org: ", responseJson.reason);
|
||||
} else {
|
||||
toast("Successfully change suborg limit!");
|
||||
if (editing === "app_executions") {
|
||||
setSubOrgStatsRows((prevRows) => {
|
||||
const newRows = [...prevRows];
|
||||
newRows[orgIndex].limit = limit;
|
||||
return newRows;
|
||||
});
|
||||
}else if (editing === "workflow_executions") {
|
||||
setSubOrgStatsRows((prevRows) => {
|
||||
const newRows = [...prevRows];
|
||||
newRows[orgIndex].workflow_usage_limit = limit;
|
||||
return newRows;
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
toast("Err: " + error.toString());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const HandleClosePopUP = () => {
|
||||
setOpen(false)
|
||||
setEditing("")
|
||||
setEditingOrgId("")
|
||||
setLimit("")
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", flexDirection: "column", marginTop: 30, minHeight: 300, marginBottom: 200, }}>
|
||||
{open && (
|
||||
<IncreaseLimitPopUp open={open} onClose={HandleClosePopUP} limit={limit} HandleEditLimit={HandleEditLimit} setLimit={setLimit} editing={editing} setEditing={setEditing} editingOrgId={editingOrgId} setEditingOrgId={setEditingOrgId}/>
|
||||
)}
|
||||
<Typography style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}>
|
||||
Child Organizations
|
||||
</Typography>
|
||||
<div style={{display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10}}>
|
||||
<Typography color="textSecondary" style={{ marginTop: 10, fontSize: 16 }}>
|
||||
View and configure execution limits for child organizations. Click the edit icon to modify app and workflow execution limits.
|
||||
</Typography>
|
||||
</div>
|
||||
{tableCreated ? (
|
||||
subOrgStatsRows.length > 0 && subOrgStatsColumns.length > 0 ? (
|
||||
<>
|
||||
<TextField
|
||||
style={{ marginBottom: 10, width: 500, marginTop: 20 }}
|
||||
variant="outlined"
|
||||
placeholder="Search organizations by name or ID"
|
||||
value={searchQuery}
|
||||
fullWidth
|
||||
InputProps={{
|
||||
style: {
|
||||
fontSize: "1em",
|
||||
height: 51,
|
||||
width: 693,
|
||||
borderRadius: 4,
|
||||
},
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<SearchIcon style={{ marginLeft: 5}} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
onChange={(e) => {
|
||||
setSearchQuery(e.target.value.toLowerCase());
|
||||
const filtered = subOrgStatsRows.filter((row) =>
|
||||
row.name.toLowerCase().includes(e.target.value.toLowerCase().trim()) ||
|
||||
row.orgId.toLowerCase().includes(e.target.value.toLowerCase().trim())
|
||||
);
|
||||
setFilteredRows(filtered);
|
||||
}}
|
||||
/>
|
||||
<DataGrid
|
||||
rows={searchQuery ? filteredRows : subOrgStatsRows}
|
||||
columns={subOrgStatsColumns}
|
||||
pageSize={rowsPerPage}
|
||||
rowsPerPageOptions={[5, 10, 25, 50]}
|
||||
onPageChange={handleChangePage}
|
||||
onPageSizeChange={handleChangeRowsPerPage}
|
||||
autoHeight
|
||||
style={{ height: "300px", width: "100%", backgroundColor: theme.palette.platformColor, color: theme.palette.text.primary }}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Typography variant="h6" color="secondary" style={{ margin: "auto",}}>
|
||||
{selectedOrganization.child_orgs.length === 0 ? "No child organizations exist." : "Unable to load child organization stats. Statistics may not be initialized yet." }
|
||||
</Typography>
|
||||
)
|
||||
) : (
|
||||
<div style={{ display: "flex", justifyContent: "center", alignItems: "center", height: "100%", margin: 'auto'}}>
|
||||
<CircularProgress style={{ color: "#FF8444" }} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const IncreaseLimitPopUp = memo(({ open, onClose, limit, setLimit, HandleEditLimit, editingOrgId, editing}) => {
|
||||
const [currentLimit, setCurrentLimit] = useState(limit)
|
||||
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
return(
|
||||
<Dialog open={open} onClose={onClose}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
|
||||
border: theme?.palette?.DialogStyle?.border,
|
||||
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: 24, fontWeight: "bold" }}>
|
||||
Increase {editing.replaceAll("_", " ").replace(/\b\w/g, c => c.toUpperCase())} Limit
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
value={currentLimit}
|
||||
onChange={(e) => setCurrentLimit(e.target.value)}
|
||||
label={`${editing.replaceAll("_", " ").replace(/\b\w/g, c => c.toUpperCase())} Limit`}
|
||||
type="string"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
InputProps={{
|
||||
style: {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
InputLabelProps={{
|
||||
style: {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
margin="normal"
|
||||
onKeyUp={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
HandleEditLimit(editingOrgId, editing, currentLimit)
|
||||
setLimit(currentLimit)
|
||||
onClose()
|
||||
}}
|
||||
}
|
||||
></TextField>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onClose} style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, marginRight: 5, color: theme.palette.primary.main }}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="contained" color="primary" onClick={() => {
|
||||
HandleEditLimit(editingOrgId, editing, currentLimit)
|
||||
setLimit(currentLimit)
|
||||
onClose()
|
||||
}} style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, marginRight: 10 }}>
|
||||
Save
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
const PaddingWrapper = memo(({ clickedFromOrgTab, children }) => {
|
||||
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
const wrapperStyle = useMemo(() => ({
|
||||
width: clickedFromOrgTab
|
||||
? "100%"
|
||||
: "auto",
|
||||
padding: "27px 10px 19px 27px",
|
||||
backgroundColor: '#212121',
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
height: '100%',
|
||||
boxSizing: 'border-box',
|
||||
overflow: 'hidden',
|
||||
maxHeight: "1700px", overflowY: "auto",scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'
|
||||
}), [clickedFromOrgTab]);
|
||||
maxHeight: "1700px",
|
||||
overflowY: "auto",
|
||||
scrollbarColor: theme.palette.scrollbarColorTransparent,
|
||||
scrollbarWidth: 'thin'
|
||||
}), [clickedFromOrgTab, theme]);
|
||||
|
||||
return (
|
||||
<div style={wrapperStyle}>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect, useContext, memo, useMemo } from 'react';
|
||||
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import classNames from "classnames";
|
||||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'
|
||||
import { DataGrid, GridColDef, GridValueGetterParams } from '@mui/x-data-grid'
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
Paper,
|
||||
Chip,
|
||||
Checkbox,
|
||||
Box,
|
||||
} from "@mui/material";
|
||||
|
||||
import {
|
||||
@@ -42,6 +43,8 @@ import { Context } from '../context/ContextApi.jsx';
|
||||
const LineChartWrapper = ({keys, inputname, height, width}) => {
|
||||
const [hovered, setHovered] = useState("");
|
||||
const inputdata = keys.data === undefined ? keys : keys.data
|
||||
const {themeMode} = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
return (
|
||||
<div style={{color: "white", border: "1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette?.borderRadius, padding: 30, marginTop: 15, backgroundColor: theme.palette.platformColor, overflow: "hidden", }}>
|
||||
@@ -83,6 +86,8 @@ const AppStats = (defaultprops) => {
|
||||
const [workflows, setWorkflows] = useState(inputWorkflows === undefined ? [] : inputWorkflows)
|
||||
const [resultRows, setResultRows] = useState([])
|
||||
const [resultLoading, setResultLoading] = useState(true)
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor)
|
||||
|
||||
const includedExecutions = selectedOrganization?.sync_features?.app_executions !== undefined ? selectedOrganization?.sync_features?.app_executions?.limit : 0
|
||||
|
||||
@@ -529,11 +534,14 @@ const AppStats = (defaultprops) => {
|
||||
|
||||
const paperStyle = {
|
||||
textAlign: "center",
|
||||
padding: 40,
|
||||
margin: 5,
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
maxWidth: 300,
|
||||
padding: "40px",
|
||||
margin: "5px",
|
||||
backgroundColor: theme.palette.cardBackgroundColor,
|
||||
border: theme.palette.defaultBorder,
|
||||
maxWidth: "300px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.cardHoverColor,
|
||||
},
|
||||
}
|
||||
|
||||
const columns: GridColDef[] = [
|
||||
@@ -646,9 +654,9 @@ const AppStats = (defaultprops) => {
|
||||
<div className="content" style={{width: "100%", margin: "auto", }}>
|
||||
<Typography style={{margin: "auto", marginLeft: 10, marginBottom: 20, fontSize: 16}} color="textSecondary">
|
||||
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"
|
||||
style={{ textDecoration: "none", color: "#FF8444",}}
|
||||
style={{ textDecoration: "none", color: theme.palette.linkColor,}}
|
||||
>Your Organisation Statistics. </a>
|
||||
It exists to give you more insight into your workflows, and to understand your utilization of the Shuffle platform. <b>The billing tracker is in Beta, and is always calculated manually before being invoiced.</b>
|
||||
</Typography>
|
||||
@@ -662,9 +670,9 @@ const AppStats = (defaultprops) => {
|
||||
The cost of app runs in the selected period based on {filteredStatistics.monthly_app_executions} App Runs. These numbers do not exclude your included 10.000/month or {includedExecutions} App Runs per month. App Run cost: ${invocationCost}.
|
||||
</Typography>
|
||||
}>
|
||||
<Paper style={paperStyle}>
|
||||
<Box sx={paperStyle}>
|
||||
<Typography variant="h4">
|
||||
${selectedOrganization.lead_info.customer === false && selectedOrganization.lead_info.pov === false ?
|
||||
${selectedOrganization?.lead_info?.customer === false && selectedOrganization?.lead_info?.pov === false ?
|
||||
0
|
||||
:
|
||||
apprunCost
|
||||
@@ -673,57 +681,49 @@ const AppStats = (defaultprops) => {
|
||||
<Typography variant="h6">
|
||||
Period Cost
|
||||
</Typography>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
<Tooltip title={
|
||||
<Typography variant="body1" style={{padding: 10, }}>
|
||||
App runs in the selected period
|
||||
</Typography>
|
||||
}>
|
||||
<Paper style={paperStyle}>
|
||||
<Box sx={paperStyle}>
|
||||
<Typography variant="h4">
|
||||
{filteredStatistics.monthly_app_executions === null || filteredStatistics.monthly_app_executions === undefined ? 0 : filteredStatistics.monthly_app_executions}
|
||||
</Typography>
|
||||
<Typography variant="h6">
|
||||
App Runs
|
||||
</Typography>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
<Tooltip title={
|
||||
<Typography variant="body1" style={{padding: 10, }}>
|
||||
Workflow runs in the selected period
|
||||
</Typography>
|
||||
}>
|
||||
<Paper style={paperStyle}>
|
||||
<Box sx={paperStyle}>
|
||||
<Typography variant="h4">
|
||||
{filteredStatistics.monthly_workflow_executions === null || filteredStatistics.monthly_workflow_executions === undefined ? 0 : filteredStatistics.monthly_workflow_executions}
|
||||
</Typography>
|
||||
<Typography variant="h6">
|
||||
Workflow Runs
|
||||
</Typography>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
<Tooltip title={
|
||||
<Typography variant="body1" style={{padding: 10, }}>
|
||||
Estimated cost to be billed at the end of the current month. Subtracted contractually included app runs. Actual cost month to date: ${monthToDateCost}. App Run cost: ${invocationCost}.
|
||||
</Typography>
|
||||
}>
|
||||
<Paper style={{
|
||||
textAlign: "center",
|
||||
padding: 40,
|
||||
margin: 5,
|
||||
marginLeft: clickedFromOrgTab? null:90,
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
maxWidth: 300,
|
||||
}}>
|
||||
<Box sx={paperStyle}>
|
||||
<Typography variant="h4">
|
||||
${monthTotalCost}
|
||||
</Typography>
|
||||
<Typography variant="h6">
|
||||
Estimated cost
|
||||
</Typography>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
</div>
|
||||
: null}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React, { useState, useEffect, useContext, memo } from "react";
|
||||
import theme from "../theme.jsx";
|
||||
import { getTheme } from "../theme.jsx";
|
||||
import { toast } from 'react-toastify';
|
||||
import ReactJson from "react-json-view-ssr";
|
||||
|
||||
import {
|
||||
Typography,
|
||||
Tooltip,
|
||||
@@ -105,6 +104,9 @@ const CacheView = memo((props) => {
|
||||
const [showFileCategoryPopup, setShowFileCategoryPopup] = React.useState(false);
|
||||
const [selectedFiles, setSelectedFiles] = useState([]);
|
||||
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
useEffect(() => {
|
||||
if (orgId?.length > 0) {
|
||||
listOrgCache(orgId, selectedCategory)
|
||||
@@ -357,12 +359,12 @@ const CacheView = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<span style={{ color: "white" }}>
|
||||
<span style={{ color: theme.palette.text.primary }}>
|
||||
{ editCache ? "Edit Key" : "Add Key"}{selectedCategory === "" || selectedCategory === "default" ? "" : ` in category '${selectedCategory}'`}
|
||||
</span>
|
||||
|
||||
</DialogTitle>
|
||||
<div style={{ paddingLeft: "30px", paddingRight: '30px', backgroundColor: "#212121", }}>
|
||||
<div style={{ paddingLeft: "30px", paddingRight: '30px', backgroundColor: theme.palette.DialogStyle.backgroundColor, }}>
|
||||
Key
|
||||
<TextField
|
||||
color="primary"
|
||||
@@ -372,7 +374,7 @@ const CacheView = memo((props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
@@ -387,7 +389,7 @@ const CacheView = memo((props) => {
|
||||
onChange={(e) => setKey(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ paddingLeft: 30, paddingRight: 30, backgroundColor: "#212121" }}>
|
||||
<div style={{ paddingLeft: 30, paddingRight: 30, backgroundColor: theme.palette.DialogStyle.backgroundColor }}>
|
||||
<div style={{display: "flex", }}>
|
||||
<Typography style={{marginTop: 25, marginBottom: 0, flex: 20, }}>
|
||||
Value - ({isValidJson.valid === true ? "Valid" : "Invalid"} JSON)
|
||||
@@ -408,7 +410,7 @@ const CacheView = memo((props) => {
|
||||
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor, marginTop: 0, }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
@@ -429,20 +431,19 @@ const CacheView = memo((props) => {
|
||||
</div>
|
||||
<DialogActions style={{ paddingLeft: "30px", paddingRight: '30px' }}>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", fontSize: 16, color: "#ff8544", textTransform:"none" }}
|
||||
style={{ borderRadius: "2px", fontSize: 16, color: theme.palette.primary.main, textTransform:"none" }}
|
||||
onClick={() => {
|
||||
setModalOpen(false)
|
||||
setKey("")
|
||||
setValue("")
|
||||
setDataValue({})
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", backgroundColor: "#ff8544",color: "#1a1a1a", textTransform:"none" }}
|
||||
style={{ borderRadius: "2px", textTransform:"none" }}
|
||||
onClick={() => {
|
||||
if (value === "") {
|
||||
toast("Key or Value can not be empty");
|
||||
@@ -563,9 +564,9 @@ const CacheView = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<div style={{ color: "rgba(255,255,255,0.9)" }}>
|
||||
<Typography variant="h5" color="textPrimary">
|
||||
Select sub-org to distribute Datastore key
|
||||
</div>
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
|
||||
<MenuItem value="none" onClick={()=> {handleSelectSubOrg(null, "none")}}>None</MenuItem>
|
||||
@@ -608,7 +609,7 @@ const CacheView = memo((props) => {
|
||||
|
||||
<div style={{ display: "flex", marginTop: 20 }}>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#ff8544" }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: theme.palette.primary.main }}
|
||||
onClick={() => setShowDistributionPopup(false)}
|
||||
color="primary"
|
||||
>
|
||||
@@ -616,7 +617,7 @@ const CacheView = memo((props) => {
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#1a1a1a", backgroundColor: "#ff8544", marginLeft: 10 }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, marginLeft: 10 }}
|
||||
onClick={() => {
|
||||
changeDistribution(selectedCacheKey, selectedSubOrg);
|
||||
}}
|
||||
@@ -630,27 +631,27 @@ const CacheView = memo((props) => {
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div style={{paddingBottom: isSelectedDataStore?null:250, minHeight: 1000, boxSizing: "border-box", width: isSelectedDataStore? "100%" :null, transition: "width 0.3s ease", padding:isSelectedDataStore?"27px 10px 27px 27px":null, height: isSelectedDataStore?"100%":null, color: isSelectedDataStore?'#ffffff':null, backgroundColor: isSelectedDataStore?'#212121':null, borderTopRightRadius: isSelectedDataStore?'8px':null, borderBottomRightRadius: isSelectedDataStore?'8px':null, borderLeft: "1px solid #494949" }}>
|
||||
<div style={{paddingBottom: isSelectedDataStore?null:250, minHeight: 1000, boxSizing: "border-box", width: isSelectedDataStore? "100%" :null, transition: "width 0.3s ease", padding:isSelectedDataStore?"27px 10px 27px 27px":null, height: isSelectedDataStore?"100%":null, color: isSelectedDataStore?'#ffffff':null, backgroundColor: isSelectedDataStore? theme.palette.platformColor :null, borderTopRightRadius: isSelectedDataStore?'8px':null, borderBottomRightRadius: isSelectedDataStore?'8px':null, borderLeft: theme.palette.defaultBorder }}>
|
||||
{modalView}
|
||||
{cacheDistributionModal}
|
||||
<div style={{height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
||||
<div style={{height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin' }}>
|
||||
<div style={{ marginTop: isSelectedDataStore?null:20, marginBottom: 20 }}>
|
||||
<h2 style={{ display: isSelectedDataStore?null: "inline" }}>Shuffle Datastore {selectedCategory === "" || selectedCategory === "default" ? "" : `- Category '${selectedCategory}'`}</h2>
|
||||
<span style={{ marginLeft: isSelectedDataStore?null:25, color:isSelectedDataStore?"#9E9E9E":null}}>
|
||||
<Typography variant="h5" style={{ display: isSelectedDataStore?null: "inline", fontWeight: 500 }}>Shuffle Datastore {selectedCategory === "" || selectedCategory === "default" ? "" : `- Category '${selectedCategory}'`}</Typography>
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginLeft: isSelectedDataStore?null:25, marginTop: 10}}>
|
||||
Datastore is a permanent key-value database for storing data that can be used cross-workflow. <br/>You can store anything from lists of IPs to complex configurations.
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/organizations#datastore"
|
||||
style={{ textDecoration: isSelectedDataStore?null:"none", color: isSelectedDataStore?"#FF8444":"#f85a3e" }}
|
||||
style={{ textDecoration: isSelectedDataStore?null:"none", color: theme.palette.linkColor }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
<Button
|
||||
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}}
|
||||
style={{fontSize: 16, textTransform: isSelectedDataStore ? 'capitalize':null, borderRadius:isSelectedDataStore?4:null, width:isSelectedDataStore?162:null, height:isSelectedDataStore?40:null}}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() =>{
|
||||
@@ -663,9 +664,9 @@ const CacheView = memo((props) => {
|
||||
Add Key
|
||||
</Button>
|
||||
<Button
|
||||
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, }}
|
||||
style={{ marginLeft: 16, marginRight: 15, borderRadius:isSelectedDataStore?4:null, width:isSelectedDataStore?81:null, height:isSelectedDataStore?40:null, }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
color="secondary"
|
||||
onClick={() => listOrgCache(orgId,selectedCategory)}
|
||||
>
|
||||
<CachedIcon />
|
||||
@@ -767,7 +768,9 @@ const CacheView = memo((props) => {
|
||||
//handleUpdateFileCategory(updateToThisCategory)
|
||||
toast.error("Not implemented.")
|
||||
}}
|
||||
style={{fontSize: 16, textTransform: 'none', color: "#1a1a1a", backgroundColor: "#ff8544"}}
|
||||
style={{fontSize: 16, textTransform: 'none', }}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
@@ -780,8 +783,9 @@ const CacheView = memo((props) => {
|
||||
{renderTextBox ?
|
||||
<Tooltip title={"Close"} style={{}} aria-label={""}>
|
||||
<Button
|
||||
style={{ marginLeft: 5, marginRight: 15, height: 35, borderRadius: 4, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
|
||||
color="primary"
|
||||
style={{ marginLeft: 5, marginRight: 15, height: 35, borderRadius: 4, textTransform: 'none', fontSize: 16,}}
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setRenderTextBox(false);
|
||||
console.log(" close clicked")
|
||||
@@ -793,8 +797,9 @@ const CacheView = memo((props) => {
|
||||
:
|
||||
<Tooltip title={"Add new file category"} style={{}} aria-label={""}>
|
||||
<Button
|
||||
style={{ marginLeft: 5, marginRight: 15, width: 169, height: 35, borderRadius: 4, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
|
||||
color="primary"
|
||||
style={{ marginLeft: 5, whiteSpace: "nowrap", marginRight: 15, width: 169, height: 35, borderRadius: 4, textTransform: 'none', fontSize: 16, }}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
setRenderTextBox(true);
|
||||
}}
|
||||
@@ -845,7 +850,7 @@ const CacheView = memo((props) => {
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.defaultBorder,
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
@@ -861,7 +866,7 @@ const CacheView = memo((props) => {
|
||||
minWidth: 800,
|
||||
overflowX: "auto",
|
||||
}}>
|
||||
<ListItem style={{width: isSelectedDataStore?"100%":null, borderBottom:isSelectedDataStore?"1px solid #494949":null, display: "table-row"}}>
|
||||
<ListItem style={{width: isSelectedDataStore?"100%":null, borderBottom:isSelectedDataStore? theme.palette.defaultBorder :null, display: "table-row"}}>
|
||||
{["Key", "Value", "Actions", "Updated", "Distribution"].map((header, index) => (
|
||||
<ListItemText
|
||||
key={index}
|
||||
@@ -872,7 +877,7 @@ const CacheView = memo((props) => {
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949"
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
@@ -883,7 +888,7 @@ const CacheView = memo((props) => {
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "table-row",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
}}
|
||||
>
|
||||
{Array(5)
|
||||
@@ -900,7 +905,7 @@ const CacheView = memo((props) => {
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
height: "20px",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
@@ -936,9 +941,9 @@ const CacheView = memo((props) => {
|
||||
return null
|
||||
}
|
||||
|
||||
var bgColor = isSelectedDataStore? "#212121":"#27292d";
|
||||
var bgColor = isSelectedDataStore? themeMode === "dark" ? "#212121" : "#FFFFFF" :"#27292d";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = isSelectedDataStore? "#1A1A1A":"#1f2023";
|
||||
bgColor = isSelectedDataStore? themeMode === "dark" ? "#1A1A1A" : "#EAEAEA" :"#1f2023";
|
||||
}
|
||||
|
||||
const validate = validateJson(data.value);
|
||||
@@ -972,11 +977,12 @@ const CacheView = memo((props) => {
|
||||
src={validate.result}
|
||||
theme={theme.palette.jsonTheme}
|
||||
style={{
|
||||
...theme.palette.reactJsonStyle,
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
border: theme.palette.defaultBorder,
|
||||
padding: 5,
|
||||
maxHeight: 300,
|
||||
overflowY: "auto",
|
||||
backgroundColor: "#151515",
|
||||
border: "1px solid rgba(255,255,255,0.7)",
|
||||
}}
|
||||
collapsed={true}
|
||||
enableClipboard={(copy) => {
|
||||
@@ -1022,7 +1028,20 @@ const CacheView = memo((props) => {
|
||||
setModalOpen(true)
|
||||
}}
|
||||
>
|
||||
<img src="/icons/editIcon.svg" alt="edit" />
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.1038 4.66848C16.3158 4.45654 16.5674 4.28843 16.8443 4.17373C17.1212 4.05903 17.418 4 17.7177 4C18.0174 4 18.3142 4.05903 18.5911 4.17373C18.868 4.28843 19.1196 4.45654 19.3315 4.66848C19.5435 4.88041 19.7116 5.13201 19.8263 5.40891C19.941 5.68582 20 5.9826 20 6.28232C20 6.58204 19.941 6.87882 19.8263 7.15573C19.7116 7.43263 19.5435 7.68423 19.3315 7.89617L8.43807 18.7896L4 20L5.21038 15.5619L16.1038 4.66848Z"
|
||||
stroke={themeMode=== "dark" ? "#F1F1F1" : "#333"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
||||
@@ -0,0 +1,846 @@
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
|
||||
import { useParams, useNavigate, Link } from "react-router-dom";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import theme from '../theme.jsx';
|
||||
import Markdown from 'react-markdown'
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
|
||||
import AppSearch from "../components/AppSearch1.jsx";
|
||||
|
||||
import {
|
||||
Divider,
|
||||
ButtonGroup,
|
||||
TextField,
|
||||
Button,
|
||||
IconButton,
|
||||
Typography,
|
||||
CircularProgress,
|
||||
Card,
|
||||
CardContent,
|
||||
} from "@mui/material";
|
||||
|
||||
import {
|
||||
Send as SendIcon,
|
||||
} from "@mui/icons-material";
|
||||
|
||||
import AuthenticationOauth2 from "../components/Oauth2Auth.jsx";
|
||||
import AuthenticationWindow from "../components/AuthenticationWindow.jsx";
|
||||
|
||||
const ChatBot = (props) => {
|
||||
const { globalUrl } = props
|
||||
const { supportEmail } = useContext(Context)
|
||||
const [messages, setMessages] = useState([])
|
||||
const [message, setMessage] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [appAuthentication, setAppAuthentication] = React.useState([]);
|
||||
const [inputAuth, setInputAuth] = useState([])
|
||||
const [forceReauthentication, setForceReauthentication] = useState(false);
|
||||
const [selectedType, setSelectedType] = useState("atomic");
|
||||
|
||||
const [appname, setAppname] = useState("");
|
||||
const [threadId, setThreadId] = useState("");
|
||||
const [runId, setRunId] = useState("");
|
||||
|
||||
const [showAppSearch, setShowAppSearch] = useState(false);
|
||||
|
||||
|
||||
const waitingMsg = "Processing..."
|
||||
const viewWidth = isMobile ? "92%" : 800
|
||||
|
||||
useEffect(() => {
|
||||
// Check if loading and remove Waiting... from messages
|
||||
const newmessages = messages
|
||||
const foundmessages = messages.filter((msg) => msg.message !== waitingMsg)
|
||||
if (foundmessages.length < newmessages.length) {
|
||||
setMessages(foundmessages);
|
||||
}
|
||||
|
||||
// Wait 0.5 second
|
||||
const objDiv = document.getElementById("messages-window");
|
||||
if (objDiv !== undefined && objDiv !== null) {
|
||||
setTimeout(() => {
|
||||
objDiv.scrollTop = objDiv.scrollHeight;
|
||||
}, 250);
|
||||
}
|
||||
}, [messages]);
|
||||
|
||||
useEffect(() => {
|
||||
if (appname === undefined || appname === null || appname === "") {
|
||||
return
|
||||
}
|
||||
|
||||
// Find the last message that was sent by us and reuse the same message content
|
||||
// with added app stuff only
|
||||
for (var i = messages.length-1; i >= 0; i--) {
|
||||
const msg = messages[i]
|
||||
if (msg.status === "sent") {
|
||||
handleSubmit(undefined, msg.message)
|
||||
break
|
||||
}
|
||||
}
|
||||
}, [appname])
|
||||
|
||||
window.title = "Shuffle - New Chat"
|
||||
let navigate = useNavigate();
|
||||
|
||||
// Automatic submit handler based on a lot of stuff :)
|
||||
const handleSubmit = (e, inputmsg) => {
|
||||
if (e !== undefined) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
setLoading(true)
|
||||
setMessage("");
|
||||
|
||||
const sentId = uuidv4();
|
||||
var parsedData = {
|
||||
"query": inputmsg,
|
||||
"thread_id": threadId,
|
||||
"run_id": runId,
|
||||
}
|
||||
|
||||
if (appname !== undefined && appname !== null && appname !== "") {
|
||||
parsedData["app_name"] = appname
|
||||
}
|
||||
|
||||
if (inputAuth !== undefined && inputAuth.length > 0) {
|
||||
// Forcing first auth app to be used in request
|
||||
try {
|
||||
parsedData["app_name"] = inputAuth[0].name
|
||||
parsedData["app_id"] = inputAuth[0].id
|
||||
parsedData["category"] = inputAuth[0].category
|
||||
parsedData["action_name"] = inputAuth[0].action_name
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
try {
|
||||
parsedData["app_name"] = inputAuth.apps[0].name
|
||||
parsedData["app_id"] = inputAuth.apps[0].id
|
||||
parsedData["category"] = inputAuth.apps[0].category
|
||||
parsedData["action_name"] = inputAuth.apps[0].action_name
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedType !== "default") {
|
||||
if (selectedType == "workflow") {
|
||||
parsedData["output_format"] = "workflow_suggestion"
|
||||
} else {
|
||||
parsedData["output_format"] = selectedType
|
||||
}
|
||||
}
|
||||
|
||||
console.log("INPUT: ", parsedData)
|
||||
|
||||
setInputAuth([])
|
||||
|
||||
var newmessages = messages;
|
||||
newmessages.push({
|
||||
"id": sentId,
|
||||
"status": "sent",
|
||||
"message": inputmsg,
|
||||
})
|
||||
newmessages.push({
|
||||
"id": sentId,
|
||||
"status": "received",
|
||||
"message": waitingMsg,
|
||||
})
|
||||
|
||||
setMessages(newmessages);
|
||||
|
||||
//fetch(`http://localhost:8080/api/v1/conversation`, {
|
||||
fetch(`${globalUrl}/api/v1/conversation`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
body: JSON.stringify(parsedData),
|
||||
})
|
||||
.then((res) => res.text())
|
||||
.then((resText) => {
|
||||
setLoading(false)
|
||||
var data = {}
|
||||
|
||||
// JSON parse
|
||||
try {
|
||||
data = JSON.parse(resText);
|
||||
} catch (e) {
|
||||
console.log("Error parsing response as JSON: ", e);
|
||||
|
||||
newmessages = newmessages.filter((msg) => msg.message !== waitingMsg);
|
||||
newmessages.push({
|
||||
"status": "received",
|
||||
"message": resText,
|
||||
"id": uuidv4(),
|
||||
});
|
||||
|
||||
setMessages(newmessages);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (data.run_id !== undefined && data.run_id !== null && data.run_id !== "") {
|
||||
setRunId(data.run_id)
|
||||
}
|
||||
|
||||
if (data.thread_id !== undefined && data.thread_id !== null && data.thread_id !== "") {
|
||||
setThreadId(data.thread_id)
|
||||
}
|
||||
|
||||
if (data.success === undefined) {
|
||||
newmessages = newmessages.filter((msg) => msg.message !== waitingMsg);
|
||||
newmessages.push({
|
||||
"status": "received",
|
||||
"message": resText,
|
||||
"id": uuidv4(),
|
||||
});
|
||||
|
||||
setMessages(newmessages);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// authentication for app
|
||||
// app validation (choose one)
|
||||
const defaultMessage = `Default output. The feature you're interacting with may not have been implemented yet. Contact ${supportEmail} with a screenshot of this and your input please.`
|
||||
|
||||
var outputmessage = defaultMessage;
|
||||
var status = "received";
|
||||
var action = ""
|
||||
if (data.success === false) {
|
||||
if (data.reason !== undefined) {
|
||||
outputmessage = data.reason
|
||||
}
|
||||
|
||||
status = "error"
|
||||
} else {
|
||||
if (data.reason !== undefined) {
|
||||
outputmessage = data.reason
|
||||
}
|
||||
}
|
||||
|
||||
if (data.action !== undefined) {
|
||||
//console.log("Action is defined: ", data.action);
|
||||
action = data.action
|
||||
|
||||
if (data.action === "app_authentication") {
|
||||
// If success & app auth -> say auth success and show available labels
|
||||
// If !success & app auth -> do authentication
|
||||
if (data.success === true) {
|
||||
newmessages = newmessages.filter((msg) => msg.message !== waitingMsg);
|
||||
// No action for this.
|
||||
// "action": action,
|
||||
var appname = ""
|
||||
if (data.apps !== undefined && data.apps !== null && data.apps.length > 0) {
|
||||
appname = data.apps[0].name.replaceAll("_", " ")
|
||||
}
|
||||
|
||||
var outputmessage = `**Please specify which ${appname} action you want to use**: \n`
|
||||
if (data.available_labels !== undefined && data.available_labels !== null && data.available_labels.length > 0) {
|
||||
for (var i = 0; i < data.available_labels.length; i++) {
|
||||
outputmessage += "* " + data.available_labels[i] + "\n"
|
||||
}
|
||||
outputmessage += "* Reauthenticate ([see auth](/admin?tab=app_auth))"
|
||||
}
|
||||
//Some opavailable actions: " + data.apps.map((app) => app.name).join(", ")
|
||||
const parsedmessage = {
|
||||
"status": status,
|
||||
"message": outputmessage,
|
||||
"id": uuidv4(),
|
||||
"category": data.category,
|
||||
|
||||
"thread_id": data.thread_id,
|
||||
"run_id": data.run_id,
|
||||
}
|
||||
newmessages.push(parsedmessage);
|
||||
setMessages(newmessages);
|
||||
|
||||
return
|
||||
|
||||
} else {
|
||||
if (data.apps !== undefined) {
|
||||
setInputAuth(data.apps)
|
||||
|
||||
setMessage(inputmsg);
|
||||
|
||||
setForceReauthentication(true)
|
||||
}
|
||||
}
|
||||
} else if (data.action === "select_category" || data.action === "select_app") {
|
||||
console.log("[DEBUG] APP SELECTION! Should help them choose an app to use")
|
||||
// Show a search field
|
||||
setShowAppSearch(true)
|
||||
}
|
||||
}
|
||||
|
||||
newmessages = newmessages.filter((msg) => msg.message !== waitingMsg);
|
||||
const parsedmessage = {
|
||||
"status": status,
|
||||
"message": outputmessage,
|
||||
"id": uuidv4(),
|
||||
"action": action,
|
||||
"category": data.category,
|
||||
|
||||
"thread_id": data.thread_id,
|
||||
"run_id": data.run_id,
|
||||
}
|
||||
newmessages.push(parsedmessage);
|
||||
setMessages(newmessages);
|
||||
console.log("New message: ", parsedmessage)
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
console.log("Problem: ", err);
|
||||
|
||||
setMessage(message);
|
||||
newmessages = newmessages.filter((msg) => msg.message !== waitingMsg);
|
||||
|
||||
// Find the message with the sentId and change the status to error
|
||||
newmessages.push({
|
||||
"status": "error",
|
||||
"message": message,
|
||||
"error_message": "Failed to send: "+err,
|
||||
"id": sentId,
|
||||
});
|
||||
setMessages(newmessages);
|
||||
});
|
||||
};
|
||||
|
||||
// Used to verify if the user is logged in after auth is done
|
||||
const getAppAuthentication = () => {
|
||||
console.log("Continue chat from the previous stage!");
|
||||
|
||||
fetch(globalUrl + "/api/v1/apps/authentication", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for app auth :O!");
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (!responseJson.success) {
|
||||
console.log("Failed to get app auth!");
|
||||
return;
|
||||
}
|
||||
|
||||
var newauth = [];
|
||||
for (let authkey in responseJson.data) {
|
||||
if (responseJson.data[authkey].defined === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
newauth.push(responseJson.data[authkey]);
|
||||
}
|
||||
|
||||
if (newauth.length > appAuthentication.length) {
|
||||
console.log("New auth is longer than old auth. Set new auth!");
|
||||
|
||||
setForceReauthentication(false)
|
||||
|
||||
// Check if last message contains "reauth"
|
||||
if (messages.length > 0) {
|
||||
const lastmessage = messages[messages.length-1];
|
||||
if (lastmessage.message.toLowerCase().includes("re-auth")) {
|
||||
console.log("Skipping resend due to reauth")
|
||||
|
||||
var newmessages = messages
|
||||
newmessages.push({
|
||||
"status": "received",
|
||||
"message": "Authentication done. What do you want to do?",
|
||||
"id": uuidv4(),
|
||||
});
|
||||
setMessages(newmessages);
|
||||
|
||||
} else {
|
||||
handleSubmit(undefined, message)
|
||||
}
|
||||
} else {
|
||||
handleSubmit(undefined, message)
|
||||
}
|
||||
}
|
||||
|
||||
setAppAuthentication(newauth)
|
||||
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("Error in getAppAuthentication: ", err);
|
||||
})
|
||||
}
|
||||
|
||||
const AuthWrapper = (props) => {
|
||||
const { app } = props;
|
||||
const [authenticationModalOpen, setAuthenticationModalOpen] = React.useState(false);
|
||||
|
||||
console.log("AUTH: ", app)
|
||||
|
||||
return (
|
||||
<div style={{position: "absolute", right: 250, bottom: 150, }}>
|
||||
{app.authentication.type === "oauth2" || app.authentication.type === "oauth2-app" ?
|
||||
<AuthenticationOauth2
|
||||
selectedApp={app}
|
||||
selectedAction={{
|
||||
"app_name": app.name,
|
||||
"app_id": app.id,
|
||||
"app_version": app.version,
|
||||
"large_image": app.large_image,
|
||||
}}
|
||||
authenticationType={app.authentication}
|
||||
isCloud={true}
|
||||
authButtonOnly={true}
|
||||
getAppAuthentication={getAppAuthentication}
|
||||
/>
|
||||
:
|
||||
<Button
|
||||
fullWidth
|
||||
variant="contained"
|
||||
style={{
|
||||
marginBottom: 20,
|
||||
marginTop: 20,
|
||||
flex: 1,
|
||||
textTransform: "none",
|
||||
textAlign: "left",
|
||||
justifyContent: "flex-start",
|
||||
backgroundColor: "#ffffff",
|
||||
color: "#2f2f2f",
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
minWidth: 300,
|
||||
maxWidth: 300,
|
||||
maxHeight: 50,
|
||||
overflow: "hidden",
|
||||
border: `1px solid ${theme.palette.inputColor}`,
|
||||
}}
|
||||
color="primary"
|
||||
fullWidth
|
||||
color="primary"
|
||||
onClick={(e) => {
|
||||
console.log("Click? ")
|
||||
e.preventDefault();
|
||||
setAuthenticationModalOpen(true);
|
||||
}}
|
||||
>
|
||||
<span style={{display: "flex"}}>
|
||||
<img
|
||||
alt={app.name}
|
||||
style={{ margin: 4, minHeight: 30, maxHeight: 30, borderRadius: theme.palette?.borderRadius, }}
|
||||
src={app.large_image}
|
||||
/>
|
||||
<Typography style={{ margin: 0, marginLeft: 10, marginTop: 5,}} variant="body1">
|
||||
Authenticate
|
||||
</Typography>
|
||||
|
||||
</span>
|
||||
</Button>
|
||||
}
|
||||
|
||||
{app.authentication.type !== "oauth2" && authenticationModalOpen ?
|
||||
<AuthenticationWindow
|
||||
selectedApp={app}
|
||||
globalUrl={globalUrl}
|
||||
getAppAuthentication={getAppAuthentication}
|
||||
appAuthentication={appAuthentication}
|
||||
authenticationModalOpen={authenticationModalOpen}
|
||||
setAuthenticationModalOpen={setAuthenticationModalOpen}
|
||||
/>
|
||||
: null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
var amountfinished = 0;
|
||||
const showAuthentication = inputAuth.map((app, index) => {
|
||||
const authexists = appAuthentication.find((auth) => auth.app.id === app.id);
|
||||
if (authexists !== undefined && forceReauthentication === false) {
|
||||
console.log("Auth exists: ", authexists);
|
||||
amountfinished += 1
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={index}>
|
||||
<AuthWrapper app={app} />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
if (amountfinished === inputAuth.length && amountfinished > 0) {
|
||||
|
||||
setInputAuth([])
|
||||
setAppAuthentication([])
|
||||
}
|
||||
|
||||
const showSamples =
|
||||
<div style={{marginLeft: 10, marginRight: 10, }}>
|
||||
<Card style={{backgroundColor: theme.palette.surfaceColor, borderRadius: theme.palette?.borderRadius,}}>
|
||||
<CardContent>
|
||||
<Typography variant="h6">
|
||||
How many incidents did we get last week?
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card style={{backgroundColor: theme.palette.surfaceColor, borderRadius: theme.palette?.borderRadius, marginTop: 10, }}>
|
||||
<CardContent>
|
||||
<Typography variant="h6">
|
||||
Answer the last email from Jim about the new project, and say we're on it
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card style={{backgroundColor: theme.palette.surfaceColor, borderRadius: theme.palette?.borderRadius, marginTop: 10, }}>
|
||||
<CardContent>
|
||||
<Typography variant="h6">
|
||||
Is the IP 1.2.3.4 blocked? If not, block it.
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
function OuterLink(props) {
|
||||
return (
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={props.href}
|
||||
style={{ color: "#f85a3e", textDecoration: "none" }}
|
||||
>
|
||||
{props.children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
function Img(props) {
|
||||
return <img style={{ borderRadius: theme.palette?.borderRadius, width: 750, maxWidth: "100%", marginTop: 15, marginBottom: 15, }} alt={props.alt} src={props.src} />;
|
||||
}
|
||||
|
||||
function CodeHandler(props) {
|
||||
//console.log("Codehandler PROPS: ", props)
|
||||
|
||||
const propvalue = props.value !== undefined && props.value !== null ? props.value : props.children !== undefined && props.children !== null && props.children.length > 0 ? props.children[0] : ""
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
minWidth: "50%",
|
||||
maxWidth: "100%",
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
overflowY: "auto",
|
||||
|
||||
// Check if props.inline === true, then do it inline
|
||||
padding: props.inline ? 0 : 15,
|
||||
display: props.inline ? "inline" : "block",
|
||||
}}
|
||||
>
|
||||
<code
|
||||
style={{
|
||||
// Wrap if larger than X
|
||||
whiteSpace: "pre-wrap",
|
||||
overflow: "auto",
|
||||
}}
|
||||
>{propvalue}</code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const markdownStyle = {
|
||||
color: "rgba(255, 255, 255, 0.65)",
|
||||
overflow: "hidden",
|
||||
paddingBottom: 100,
|
||||
margin: "auto",
|
||||
maxWidth: "100%",
|
||||
minWidth: "100%",
|
||||
overflow: "hidden",
|
||||
fontSize: isMobile ? "1.3rem" : "1.0rem",
|
||||
}
|
||||
|
||||
const Heading = (props) => {
|
||||
const element = React.createElement(
|
||||
`h${props.level}`,
|
||||
{ style: { marginTop: props.level === 1 ? 20 : 50 } },
|
||||
props.children
|
||||
);
|
||||
const [hover, setHover] = useState(false);
|
||||
|
||||
var extraInfo = "";
|
||||
return (
|
||||
<Typography
|
||||
onMouseOver={() => {
|
||||
setHover(true);
|
||||
}}
|
||||
>
|
||||
{props.level !== 1 ? (
|
||||
<Divider
|
||||
style={{
|
||||
width: "90%",
|
||||
marginTop: 40,
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{element}
|
||||
{/*hover ? <LinkIcon onMouseOver={() => {setHover(true)}} style={{cursor: "pointer", display: "inline", }} onClick={() => {
|
||||
window.location.href += "#hello"
|
||||
console.log(window.location)
|
||||
//window.history.pushState('page2', 'Title', '/page2.php');
|
||||
//window.history.replaceState('page2', 'Title', '/page2.php');
|
||||
}} />
|
||||
: ""
|
||||
*/}
|
||||
{extraInfo}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
const OrderedList = (props) => {
|
||||
var parsedchildren = []
|
||||
for (var i = 0; i < props.children.length; i++) {
|
||||
const child = props.children[i]
|
||||
if (child === "\n") {
|
||||
continue
|
||||
}
|
||||
|
||||
if (child.props !== undefined && child.props.children !== undefined) {
|
||||
// Remove <p> from the child wrapper
|
||||
var parsedchild = []
|
||||
for (var j = 0; j < child.props.children.length; j++) {
|
||||
const childchild = child.props.children[j]
|
||||
// print the raw childchild bytes, not string
|
||||
if (childchild === "\n") {
|
||||
continue
|
||||
}
|
||||
|
||||
// If the childchild has <p> around it, remove it
|
||||
parsedchild.push(childchild)
|
||||
|
||||
/*
|
||||
// Not doing this as it breaks links
|
||||
if (childchild.props !== undefined && childchild.props.children !== undefined) {
|
||||
parsedchild.push(childchild.props.children)
|
||||
} else {
|
||||
parsedchild.push(childchild)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
parsedchildren.push(parsedchild)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ol style={{marginTop: 0, }}>
|
||||
{parsedchildren.map((child, index) => {
|
||||
return (
|
||||
<li key={index} style={{minHeight: 0, display: "block", }}>
|
||||
<p style={{marginTop: 0, marginBottom: 10, }}>
|
||||
{index+1}. {child}
|
||||
</p>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ol>
|
||||
)
|
||||
}
|
||||
|
||||
const Paragraph = (props) => {
|
||||
return (
|
||||
<p style={{marginTop: 15, marginBottom: 15, }}>
|
||||
{props.children}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
const markdownComponents = {
|
||||
ol: OrderedList,
|
||||
ul: OrderedList,
|
||||
img: Img,
|
||||
code: CodeHandler,
|
||||
h1: Heading,
|
||||
h2: Heading,
|
||||
h3: Heading,
|
||||
h4: Heading,
|
||||
h5: Heading,
|
||||
h6: Heading,
|
||||
a: OuterLink,
|
||||
p: Paragraph,
|
||||
}
|
||||
|
||||
const chatWindow =
|
||||
<div style={{minWidth: viewWidth, maxWidth: viewWidth, margin: "auto", textAlign: "left", minHeight: 1500, }}>
|
||||
{messages.length === 0 ?
|
||||
<span>
|
||||
<h1>Shuffle AI</h1>
|
||||
|
||||
|
||||
|
||||
{showSamples}
|
||||
</span>
|
||||
: null}
|
||||
<div
|
||||
id="messages-window"
|
||||
style={{
|
||||
marginTop: 50,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
minHeight: 1500,
|
||||
maxHeight: isMobile ? "85%" : "85%",
|
||||
overflow: "auto", paddingBottom: 200,
|
||||
}}
|
||||
>
|
||||
{messages.map((message, index) => {
|
||||
const float = message.status === "sent" ? "left" : "right";
|
||||
const border = message.status === "error" ? "red" : "rgba(255,255,255,0.3)"
|
||||
|
||||
const hasAction = message.action !== undefined && message.action !== null && message.action !== ""
|
||||
|
||||
return (
|
||||
// Make a chat bubble component
|
||||
<div key={index} style={{position: "relative", width: "100%", marginTop: 15, marginLeft: isMobile ? 10 : 0, }}>
|
||||
<Typography variant="body1" style={{display: "flex", backgroundColor: theme.palette.surfaceColor, color: "white", padding: "0px 10px 0px 10px", borderRadius: theme.palette?.borderRadius, float: float, border: `1px solid ${border}`, "cursor": hasAction ? "pointer" : "default", maxWidth: viewWidth-30, overflowWrap: "break-word", whiteSpace: "pre-line" }} onClick={() => {
|
||||
if (!hasAction) {
|
||||
return
|
||||
}
|
||||
|
||||
if (message.action === "login") {
|
||||
navigate("/login?view=/conversation&message=You must log in to use ShuffleGPT")
|
||||
} else if (message.action === "app_authentication") {
|
||||
console.log("App auth action!")
|
||||
//setAuthenticationModalOpen(true)
|
||||
} else {
|
||||
console.log("\n\nUnknown click action: ", message.action)
|
||||
}
|
||||
}}>
|
||||
{message.message === waitingMsg ? <CircularProgress style={{height: 20, width: 20, marginTop: 20, marginRight: 10, }} /> : null}
|
||||
<span>
|
||||
<Markdown
|
||||
components={markdownComponents}
|
||||
id="markdown_wrapper"
|
||||
style={{
|
||||
minHeight: 20,
|
||||
marginTop: 0,
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
}}
|
||||
>
|
||||
{message.message}
|
||||
</Markdown>
|
||||
|
||||
{message.thread_id !== undefined && message.thread_id !== null && message.thread_id !== "" ?
|
||||
<Typography variant="body2" style={{color: "rgba(255,255,255,0.5)", marginTop: 5, }}>
|
||||
Thread: {message.thread_id}
|
||||
</Typography>
|
||||
: null
|
||||
}
|
||||
</span>
|
||||
</Typography>
|
||||
|
||||
{message.status === "error" && message.error_message ?
|
||||
<Typography variant="body2" style={{color: "red", }}>
|
||||
{message.error_message}
|
||||
</Typography>
|
||||
: null}
|
||||
|
||||
{(message.action === "select_category" || message.action === "select_app") && showAppSearch && index === messages.length-1 ?
|
||||
<div style={{position: "absolute", right: 0, bottom: -100, }}>
|
||||
<AppSearch
|
||||
placeholder={"Find your "+message.category+" app"}
|
||||
setNewSelectedApp={setAppname}
|
||||
/>
|
||||
</div>
|
||||
: null}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{showAuthentication}
|
||||
|
||||
<div style={{position: "fixed", bottom: 0, left: 0, width: "100%", zIndex: 100, backgroundColor: theme.palette.platformColor, }}>
|
||||
<div style={{width: viewWidth, margin: "auto", }}>
|
||||
{messages.length === 0 ?
|
||||
<span>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
Query Type
|
||||
</Typography>
|
||||
<ButtonGroup
|
||||
fullWidth
|
||||
color="secondary"
|
||||
style={{display: "flex", marginTop: 10, }}
|
||||
>
|
||||
{/*
|
||||
<Button
|
||||
fullWidth
|
||||
disabled
|
||||
variant={selectedType === "default" ? "contained" : "outlined"}
|
||||
onClick={() => setSelectedType("default")}
|
||||
>
|
||||
Auto
|
||||
</Button>
|
||||
*/}
|
||||
<Button
|
||||
fullWidth
|
||||
variant={selectedType === "atomic" ? "contained" : "outlined"}
|
||||
onClick={() => setSelectedType("atomic")}
|
||||
>
|
||||
Auto-run action
|
||||
</Button>
|
||||
<Button
|
||||
fullWidth
|
||||
variant={selectedType === "support" ? "contained" : "outlined"}
|
||||
onClick={() => setSelectedType("support")}
|
||||
>
|
||||
Support
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</span>
|
||||
: null}
|
||||
|
||||
<form onSubmit={(e) => handleSubmit(e, message)} style={{bottom: 20, marginTop: 10, marginBottom: isMobile ? 0 : 10, maxWidth: viewWidth, minWidth: viewWidth, }}>
|
||||
<TextField
|
||||
id="message"
|
||||
fullWidth
|
||||
disabled={loading}
|
||||
label="Send a message"
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
variant="outlined"
|
||||
autoFocus
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<IconButton
|
||||
aria-label="send message"
|
||||
onClick={(e) => handleSubmit(e, message)}
|
||||
>
|
||||
<SendIcon color="primary" />
|
||||
</IconButton>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
</form>
|
||||
{isMobile ? null :
|
||||
<Typography variant="body2" color="textSecondary" align="center" style={{marginTop: 0,}} >
|
||||
{`The Shuffle AI is a test system for automatic workflow generation and atomic functions for the future of Shuffle. Shuffle AI may use your organization info in the query, and attempts to auto-correct any failed behavior. If you have any questions, please contact us at ${supportEmail}`}
|
||||
</Typography>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
return (
|
||||
<div style={{width: isMobile ? "100%" : 1000, margin: "auto", paddingTop: 50, }}>
|
||||
{chatWindow}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChatBot;
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
Visibility as VisibilityIcon,
|
||||
VisibilityOff as VisibilityOffIcon,
|
||||
} from "@mui/icons-material";
|
||||
import theme from "../theme.jsx";
|
||||
import { getTheme } from "../theme.jsx";
|
||||
import { styled } from '@mui/styles';
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
@@ -48,6 +48,8 @@ const CloudSyncTab = (props) => {
|
||||
const [, forceUpdate] = React.useState();
|
||||
const itemColor = "white";
|
||||
const isCloud = window?.location?.host === "localhost:3002" || window?.location?.host === "shuffler.io";
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
useEffect(() => { getSettings(); }, []);
|
||||
const GridItem = (props) => {
|
||||
const [expanded, setExpanded] = React.useState(false);
|
||||
@@ -167,9 +169,9 @@ const CloudSyncTab = (props) => {
|
||||
<div
|
||||
style={{
|
||||
margin: 4,
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
borderRadius: 8,
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
minHeight: expanded ? 250 : "inherit",
|
||||
maxHeight: expanded ? 300 : "inherit",
|
||||
boxShadow: "none",
|
||||
@@ -188,13 +190,13 @@ const CloudSyncTab = (props) => {
|
||||
<Avatar>{primaryIcon}</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
style={{ textTransform: "capitalize", color: "#F1F1F1", fontSize: 14, fontWeight: 400, }}
|
||||
style={{ textTransform: "capitalize", color: theme.palette.text.primary, fontSize: 14, fontWeight: 400, }}
|
||||
primary={primary}
|
||||
/>
|
||||
{isCloud && userdata.support === true ?
|
||||
<Tooltip title="Edit features (support users only)">
|
||||
<EditIcon
|
||||
color="secondary"
|
||||
color="textPrimary"
|
||||
style={{ marginRight: 10, cursor: "pointer", }}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
@@ -527,20 +529,20 @@ const CloudSyncTab = (props) => {
|
||||
return (
|
||||
<div style={{padding: "27px 10px 19px 27px",}}>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<h2
|
||||
style={{ marginBottom: 8, marginTop: 0, color: "#ffffff" }}
|
||||
<Typography variant="h5"
|
||||
style={{ marginBottom: 8, marginTop: 0, fontWeight: 500}}
|
||||
>
|
||||
Cloud syncronization
|
||||
</h2>
|
||||
<span style={{ color: "#C8C8C8", fontSize: 16, fontWeight: 400, }}>
|
||||
What does <a href="/docs/organizations#cloud_sync" target="_blank" rel="noopener noreferrer" style={{ color: "rgba(255, 132, 68, 1)", fontSize: 16, textDecoration: 'none', }}>cloud sync</a> do? Cloud synchronization is a way of getting more out of Shuffle. Shuffle will ALWAYS make every option open source, but features relying on other users can't be done without a collaborative approach.
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography variant="body2" style={{ color: theme.palette.text.secondary, fontSize: 16, fontWeight: 400, }}>
|
||||
What does <a href="/docs/organizations#cloud_sync" target="_blank" rel="noopener noreferrer" style={{ color: theme.palette.linkColor, fontSize: 16, textDecoration: 'none', }}>cloud sync</a> do? Cloud synchronization is a way of getting more out of Shuffle. Shuffle will ALWAYS make every option open source, but features relying on other users can't be done without a collaborative approach.
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
{isCloud ? (
|
||||
<div style={{ marginTop: 15, display: "flex" }}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<Typography style={{fontWeight: 400, fontSize: 16, color: "#F1F1F1"}}>
|
||||
<Typography style={{fontWeight: 400, fontSize: 16, color: theme.palette.text.secondary}}>
|
||||
Currently syncronizing:{" "}
|
||||
{selectedOrganization.cloud_sync_active === true
|
||||
? <span style={{ color: "#4CFD72", fontSize: 16, marginLeft: 16}}>True</span>
|
||||
@@ -561,28 +563,31 @@ const CloudSyncTab = (props) => {
|
||||
marginRight: 10,
|
||||
fontSize: 16,
|
||||
fontWeight: 400,
|
||||
color: theme.palette.text.primary,
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
}}
|
||||
>
|
||||
Your Api key
|
||||
</Typography>
|
||||
{userSettings?.apikey === undefined || userSettings?.apikey === null || userSettings?.apikey?.length <=0 ? (
|
||||
<Skeleton variant="rectangular" animation="wave" sx={{backgroundColor: '#212121', border: '1px solid #646464', width: 500, height: 50, marginTop: 2 }}/>
|
||||
<Skeleton variant="rectangular" animation="wave" sx={{backgroundColor: theme.palette.loaderColor, border: '1px solid #646464', width: 500, height: 50, marginTop: 2 }}/>
|
||||
):
|
||||
<div style={{ display: "flex" }}>
|
||||
<TextField
|
||||
color="primary"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
borderRadius: theme.palette.textFieldStyle.borderRadius,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
maxWidth: 500,
|
||||
height: 35
|
||||
}}
|
||||
InputProps={{
|
||||
sx: {
|
||||
height: "35px",
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: "1em",
|
||||
backgroundColor: '#212121',
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
borderRadius: theme.palette.textFieldStyle.borderRadius,
|
||||
},
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
@@ -701,10 +706,10 @@ const CloudSyncTab = (props) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<h2 style={{ marginLeft: 5, marginTop: 40, marginBottom: 5 }}>
|
||||
<Typography variant="h5" style={{ marginLeft: 5, marginTop: 40, marginBottom: 5 }}>
|
||||
Features
|
||||
</h2>
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginBottom: 24, fontSize: 16, fontWeight: 400, marginLeft: 5, color: "#C8C8C8" }}>
|
||||
</Typography>
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginBottom: 24, fontSize: 16, fontWeight: 400, marginLeft: 5, color: theme.palette.text.secondary }}>
|
||||
Features and Limitations that are currently available to you in your Cloud or Hybrid Organization. App Executions (App Runs) reset monthly. If the organization is a customer or in a trial, these features limitations are not always enforced. </Typography>
|
||||
<Grid container style={{ width: "100%", marginBottom: 15, }}>
|
||||
|
||||
@@ -728,7 +733,7 @@ const CloudSyncTab = (props) => {
|
||||
variant="rectangular"
|
||||
height={50}
|
||||
width={343}
|
||||
sx={{ backgroundColor: '#1a1a1a', display: 'flex', borderRadius: 1 }}
|
||||
sx={{ backgroundColor: theme.palette.loaderColor, display: 'flex', borderRadius: 1 }}
|
||||
animation="wave"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
import { useInterval } from "react-powerhooks";
|
||||
import { toast } from 'react-toastify';
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import WorkflowValidationTimeline from "../components/WorkflowValidationTimeline.jsx"
|
||||
|
||||
import {
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
Collapse,
|
||||
IconButton,
|
||||
} from "@mui/material";
|
||||
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import {
|
||||
FavoriteBorder as FavoriteBorderIcon,
|
||||
Error as ErrorIcon,
|
||||
@@ -76,6 +76,8 @@ const ConfigureWorkflow = (props) => {
|
||||
const [showFinalizeAnimation, setShowFinalizeAnimation] = React.useState(false);
|
||||
const [loopRunning, setLoopRunning] = useState(false)
|
||||
const [checkStarted, setCheckStarted] = React.useState(false);
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
useEffect(() => {
|
||||
if (requiredActions.length === 0) {
|
||||
@@ -799,7 +801,7 @@ const ConfigureWorkflow = (props) => {
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
border: filled ? `1px solid ${theme.palette.green}` : "1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette?.borderRadius, width: "100%", padding: 12, cursor: filled ? "default" : "pointer",
|
||||
border: filled ? `1px solid ${theme.palette.green}` : theme.palette.textFieldStyle.border, borderRadius: theme.palette?.borderRadius, width: "100%", padding: 12, cursor: filled ? "default" : "pointer",
|
||||
}}
|
||||
id="app-config"
|
||||
>
|
||||
|
||||
@@ -3,6 +3,8 @@ import OrgHeaderexpanded from "../components/OrgHeaderexpandedNew.jsx";
|
||||
import OrgHeader from '../components/OrgHeaderNew.jsx';
|
||||
import { toast } from "react-toastify";
|
||||
import CloudSyncTab from '../components/CloudSyncTab.jsx';
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
import { getTheme } from '../theme.jsx';
|
||||
import {
|
||||
FileCopy as FileCopyIcon,
|
||||
} from "@mui/icons-material";
|
||||
@@ -10,6 +12,7 @@ import {
|
||||
Button,
|
||||
Tooltip,
|
||||
IconButton,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
|
||||
const EditOrgTab = (props) => {
|
||||
@@ -33,6 +36,9 @@ const EditOrgTab = (props) => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
const handleStatusChange = (event) => {
|
||||
const { value } = event.target;
|
||||
setSelectedStatus(value);
|
||||
@@ -283,23 +289,23 @@ If you're interested, please let me know a time that works for you, or set up a
|
||||
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%", boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121', borderRadius: '16px', }}>
|
||||
<div style={{ height: "100%", width: "100%", overflowX: 'hidden', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}} >
|
||||
<div style={{ width: "100%", boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: theme.palette.platformColor, borderRadius: '16px', }}>
|
||||
<div style={{ height: "100%", width: "100%", overflowX: 'hidden', scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}} >
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{display:"flex"}}>
|
||||
<div style={{width:'70%'}}>
|
||||
<h2 style={{ marginBottom: 8, marginTop: 0, color: "#ffffff" }}>Organization overview</h2>
|
||||
<span style={{ color: "#9E9E9E" }}>
|
||||
<Typography variant='h3' sx={{ marginBottom: "15px", marginTop: 0, }}>Organization overview</Typography>
|
||||
<Typography variant="body2" style={{ color: theme.palette.text.secondary, fontSize: 16 }}>
|
||||
On this page organization admins can configure organisations, and sub-orgs (MSSP).{" "}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/organizations#organization"
|
||||
style={{ color: "#FF8444" }}
|
||||
style={{ color: theme.palette.linkColor, }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
<div style={{display:"flex", alignItems:"center", marginLeft:50}}>
|
||||
<Tooltip
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useContext } from "react";
|
||||
import theme from '../theme.jsx';
|
||||
import { getTheme } from '../theme.jsx';
|
||||
import { isMobile } from "react-device-detect"
|
||||
import { MuiChipsInput } from "mui-chips-input";
|
||||
import { toast } from "react-toastify"
|
||||
@@ -46,7 +46,7 @@ import {
|
||||
Slider,
|
||||
|
||||
} from "@mui/material";
|
||||
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import {
|
||||
DatePicker,
|
||||
LocalizationProvider,
|
||||
@@ -69,7 +69,8 @@ const EditWorkflow = (props) => {
|
||||
const { globalUrl, workflow, setWorkflow, modalOpen, setModalOpen, showUpload, usecases, setNewWorkflow, appFramework, isEditing, userdata, apps, saveWorkflow, expanded, scrollTo, setRealtimeMarkdown, boxWidth, setBoxWidth, } = props
|
||||
|
||||
const [_, setUpdate] = React.useState(""); // Used for rendering, don't remove
|
||||
|
||||
const {themeMode, brandColor} = useContext(Context)
|
||||
const theme = getTheme(themeMode, brandColor)
|
||||
const [submitLoading, setSubmitLoading] = React.useState(false);
|
||||
const [showMoreClicked, setShowMoreClicked] = React.useState(isEditing !== false ? true : false);
|
||||
|
||||
@@ -203,23 +204,27 @@ const EditWorkflow = (props) => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
PaperProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
minWidth: isMobile ? "90%" : 650,
|
||||
maxWidth: isMobile ? "90%" : 650,
|
||||
minHeight: 400,
|
||||
paddingTop: 25,
|
||||
paddingLeft: 50,
|
||||
sx: {
|
||||
color: theme.palette.DialogStyle.color,
|
||||
minWidth: isMobile ? "90%" : "650px",
|
||||
maxWidth: isMobile ? "90%" : "650px",
|
||||
minHeight: "400px",
|
||||
//minWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550,
|
||||
//maxWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
backgroundColor: "black",
|
||||
borderRadius: theme.palette.DialogStyle.borderRadius,
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
'& .MuiDialogContent-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
'& .MuiDialogTitle-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogTitle style={{ padding: 30, paddingBottom: 0, zIndex: 1000, }}>
|
||||
<DialogTitle style={{ padding: 30, paddingBottom: 0, zIndex: 1000, paddingTop: "25px", paddingLeft: "50px"}}>
|
||||
<div style={{ display: "flex" }}>
|
||||
<div style={{ flex: 1, color: "rgba(255,255,255,0.9)" }}>
|
||||
<div style={{ flex: 1, color: theme.palette.textColor }}>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Typography variant="h4" style={{ flex: 9, }}>
|
||||
{newWorkflow ? "New" : "Editing"} workflow
|
||||
@@ -248,7 +253,7 @@ const EditWorkflow = (props) => {
|
||||
|
||||
</div>
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginTop: 20, maxWidth: 440, }}>
|
||||
Workflows can be built from scratch, or from templates. <a href="/usecases2" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Usecases</a> can help you discover next steps, and you can <a href="/search?tab=workflows" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>search</a> for them directly. <a href="/docs/workflows" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Learn more</a>
|
||||
Workflows can be built from scratch, or from templates. <a href="/usecases2" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: theme.palette.linkColor }}>Usecases</a> can help you discover next steps, and you can <a href="/search?tab=workflows" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: theme.palette.linkColor }}>search</a> for them directly. <a href="/docs/workflows" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color:theme.palette.linkColor }}>Learn more</a>
|
||||
</Typography>
|
||||
|
||||
<div style={{marginTop: 10, marginBottom: 10, marginRight: 50, }}>
|
||||
@@ -288,16 +293,16 @@ const EditWorkflow = (props) => {
|
||||
</DialogTitle>
|
||||
<FormControl>
|
||||
<div style={{
|
||||
borderTop: "1px solid rgba(255,255,255,0.5)",
|
||||
borderTop: theme.palette.defaultBorder,
|
||||
width: 600,
|
||||
position: "fixed",
|
||||
right: 20,
|
||||
bottom: 0,
|
||||
zIndex: 1002,
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
backgroundColor: theme.palette.DialogStyle.backgroundColor,
|
||||
height: 75,
|
||||
paddingTop: 20,
|
||||
paddingLeft: 75,
|
||||
paddingLeft: 30,
|
||||
}}>
|
||||
<Button
|
||||
variant="contained"
|
||||
@@ -388,7 +393,7 @@ const EditWorkflow = (props) => {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<DialogContent style={{ paddingTop: 10, display: "flex", minHeight: 300, zIndex: 1001, paddingBottom: 200, }}>
|
||||
<DialogContent style={{ paddingTop: 10, display: "flex", minHeight: 300, zIndex: 1001, paddingBottom: 200, paddingLeft: "50px" }}>
|
||||
<div style={{ minWidth: newWorkflow ? 500 : 550, maxWidth: newWorkflow ? 450 : 500, }}>
|
||||
<TextField
|
||||
onChange={(event) => {
|
||||
@@ -396,7 +401,7 @@ const EditWorkflow = (props) => {
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -469,7 +474,7 @@ const EditWorkflow = (props) => {
|
||||
style={{ flex: 1, maxHeight: 120, overflow: "auto", }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
}}
|
||||
placeholder="Tags"
|
||||
@@ -1287,7 +1292,7 @@ const EditWorkflow = (props) => {
|
||||
|
||||
|
||||
{newWorkflow === true ?
|
||||
<span style={{ marginTop: 30, }}>
|
||||
<span style={{ paddingTop: 30, backgroundColor: theme.palette.DialogStyle.backgroundColor }}>
|
||||
<Typography variant="h6" style={{ marginLeft: 30, paddingBottom: 0, }}>
|
||||
Relevant Workflows
|
||||
</Typography>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { memo, useContext, useEffect, useState } from 'react';
|
||||
import theme from "../theme.jsx";
|
||||
import { getTheme } from "../theme.jsx";
|
||||
import {
|
||||
Tooltip,
|
||||
Typography,
|
||||
@@ -62,6 +62,9 @@ const EnvironmentTab = memo((props) => {
|
||||
const [selectedSubOrg, setSelectedSubOrg] = React.useState([]);
|
||||
const [showLocationActionModal, setShowLocationActionModal] = React.useState(undefined)
|
||||
|
||||
const { themeMode, supportEmail, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getEnvironments();
|
||||
@@ -370,7 +373,7 @@ const EnvironmentTab = memo((props) => {
|
||||
})
|
||||
.catch((error) => {
|
||||
toast(
|
||||
"Failed dismissing alert. Please contact support@shuffler.io if this persists.",
|
||||
`Failed dismissing alert. Please contact ${supportEmail} if this persists.`,
|
||||
);
|
||||
});
|
||||
};
|
||||
@@ -512,11 +515,11 @@ const EnvironmentTab = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<span style={{ color: "white" }}>Add Location</span>
|
||||
<Typography variant='h5' color="textPrimary" >Add Location</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<div>
|
||||
Location Name
|
||||
<Typography variant='body2' color="textPrimary">Location Name</Typography>
|
||||
<TextField
|
||||
color="primary"
|
||||
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor,}}
|
||||
@@ -524,7 +527,7 @@ const EnvironmentTab = memo((props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
@@ -539,19 +542,18 @@ const EnvironmentTab = memo((props) => {
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{loginInfo} {/* Assuming loginInfo is part of the relevant content */}
|
||||
{loginInfo}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", color: "#ff8544" }}
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", color: theme.palette.primary.main, }}
|
||||
onClick={() => setModalOpen(false)}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", backgroundColor: "#ff8544", color: "#1a1a1a" }}
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", }}
|
||||
onClick={() => {
|
||||
submitEnvironment(modalUser); // Assuming modalUser is available
|
||||
}}
|
||||
@@ -733,9 +735,9 @@ const EnvironmentTab = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<div style={{ color: "rgba(255,255,255,0.9)" }}>
|
||||
<Typography variant='h5' color="textPrimary" >
|
||||
Select sub-org to distribute Environments
|
||||
</div>
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
|
||||
<MenuItem value="none" onClick={()=> {handleSelectSubOrg(null, "none")}}>None</MenuItem>
|
||||
@@ -778,7 +780,7 @@ const EnvironmentTab = memo((props) => {
|
||||
|
||||
<div style={{ display: "flex", marginTop: 20 }}>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#ff8544" }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: theme.palette.primary.main }}
|
||||
onClick={() => setShowDistributionPopup(false)}
|
||||
color="primary"
|
||||
>
|
||||
@@ -786,7 +788,7 @@ const EnvironmentTab = memo((props) => {
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#1a1a1a", backgroundColor: "#ff8544", marginLeft: 10 }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, marginLeft: 10 }}
|
||||
onClick={() => {
|
||||
changeDistribution(selectedEnvironment, selectedSubOrg);
|
||||
}}
|
||||
@@ -800,27 +802,27 @@ const EnvironmentTab = memo((props) => {
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121',borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949", }}>
|
||||
<div style={{ width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: theme.palette.platformColor,borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: theme.palette.defaultBorder, }}>
|
||||
{modalView}
|
||||
{EnvironmentDistributionModal}
|
||||
<div style={{ height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin' }}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<h2 style={{ marginBottom: 8, marginTop: 0, color: "#ffffff" }}>Runtime Locations</h2>
|
||||
<span style={{ color: textColor }}>
|
||||
Decides which Orborus <b>runtime location</b> to run your workflows in. Previously called Environments. <br /> If you have scale problems, <a href="https://shuffler.io/docs/configuration#high-availability" target="_blank" rel="noopener noreferrer" style={{ color: "#FF8444" }}>check the docs</a> or talk to our team: support@shuffler.io.
|
||||
<Typography variant='h5' color="textPrimary" style={{ marginBottom: 8, marginTop: 0,}}>Runtime Locations</Typography>
|
||||
<Typography variant='body2' color="textSecondary">
|
||||
Decides which Orborus <b>runtime location</b> to run your workflows in. Previously called Environments. <br /> If you have scale problems, <a href="https://shuffler.io/docs/configuration#high-availability" target="_blank" rel="noopener noreferrer" style={{ color: theme.palette.linkColor }}>check the docs</a> or talk to our team: {supportEmail}.
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/organizations#locations"
|
||||
style={{ color: "#FF8444" }}
|
||||
style={{ color: theme.palette.linkColor, }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
<Button
|
||||
style={{ backgroundColor: '#ff8544', color: "#1a1a1a", borderRadius: 4, textTransform: "capitalize", fontSize: 16, }}
|
||||
style={{ borderRadius: 4, textTransform: "capitalize", fontSize: 16, }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => setModalOpen(true)}
|
||||
@@ -828,9 +830,9 @@ const EnvironmentTab = memo((props) => {
|
||||
Add Location
|
||||
</Button>
|
||||
<Button
|
||||
style={{ backgroundColor: "#2F2F2F", borderRadius: 4, width: 81, height: 40, marginLeft: 16, marginRight: 15 }}
|
||||
style={{ borderRadius: 4, width: 81, height: 40, marginLeft: 16, marginRight: 15 }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
color="secondary"
|
||||
onClick={getEnvironments}
|
||||
>
|
||||
<CachedIcon />
|
||||
@@ -851,7 +853,7 @@ const EnvironmentTab = memo((props) => {
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.defaultBorder,
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
@@ -873,7 +875,7 @@ const EnvironmentTab = memo((props) => {
|
||||
width: "100%",
|
||||
minWidth: 800,
|
||||
paddingBottom: 0,
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
}}
|
||||
>
|
||||
{["Type", "Status", "Scale", "Pipeline", "Name", "Type", "Queue", "Actions", "Distribution"].map((header, index) => {
|
||||
@@ -901,7 +903,7 @@ const EnvironmentTab = memo((props) => {
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "80px 80px 80px 120px 120px 120px 120px 350px 150px",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
height: 40,
|
||||
width: "100%",
|
||||
boxSizing: "border-box",
|
||||
@@ -919,7 +921,7 @@ const EnvironmentTab = memo((props) => {
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
/>
|
||||
@@ -941,9 +943,9 @@ const EnvironmentTab = memo((props) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bgColor = "#212121";
|
||||
var bgColor = themeMode === "dark" ? "#212121" : "#FFFFFF";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = "#1A1A1A";
|
||||
bgColor = themeMode === "dark" ? "#1A1A1A" : "#EAEAEA";
|
||||
}
|
||||
|
||||
// Check if there's a notification for it in userdata.priorities
|
||||
@@ -1013,7 +1015,9 @@ const EnvironmentTab = memo((props) => {
|
||||
environment.name === "Cloud" ? (
|
||||
<Tooltip title="Cloud" placement="top">
|
||||
<CloudIcon
|
||||
style={{ color: "rgba(255,255,255,0.8)" }}
|
||||
style={{
|
||||
color: themeMode === "dark" ? "#CCCCCC" : "#333333",
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : environment.run_type === "docker" ? (
|
||||
@@ -1075,7 +1079,7 @@ const EnvironmentTab = memo((props) => {
|
||||
:
|
||||
<span>IP / label: {environment?.running_ip?.split(":")[0]}. May stay running up to a minute after stopping Orborus.</span>
|
||||
:
|
||||
"Cloud is automatically configured. Reachout to support@shuffler.io if you have any questions."
|
||||
`Cloud is automatically configured. Reachout to ${supportEmail} if you have any questions.`
|
||||
}
|
||||
|
||||
<br />
|
||||
@@ -1169,7 +1173,7 @@ const EnvironmentTab = memo((props) => {
|
||||
<ListItemText
|
||||
primary={
|
||||
environment.Type === "cloud" ?
|
||||
<Tooltip title={"Make a new environment to set up a Datalake node. Please contact support@shuffler.io if this is something you want to see on Cloud directly."} placement="top">
|
||||
<Tooltip title={`Make a new environment to set up a Datalake node. Please contact ${supportEmail} if this is something you want to see on Cloud directly.`} placement="top">
|
||||
<CancelIcon style={{ color: "rgba(255,255,255,0.3)" }} />
|
||||
</Tooltip>
|
||||
:
|
||||
@@ -1267,13 +1271,12 @@ const EnvironmentTab = memo((props) => {
|
||||
/>
|
||||
<ListItemText
|
||||
style={{
|
||||
minWidth: 300,
|
||||
overflow: "hidden",
|
||||
minWidth: 350,
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "flex", flexWrap: "nowrap" }}>
|
||||
<ButtonGroup
|
||||
style={{ borderRadius: "5px 5px 5px 5px", flexWrap: "nowrap" }}
|
||||
style={{ borderRadius: "5px 5px 5px 5px", flexWrap: "nowrap", width: "100%" }}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
@@ -1369,7 +1372,7 @@ const EnvironmentTab = memo((props) => {
|
||||
</ButtonGroup>
|
||||
|
||||
<IconButton disabled={environment.Type === "cloud"} onClick={()=> {setIsExpanded(prev => !prev)}}>
|
||||
{listItemExpanded === index ? <ExpandLessIcon /> : <ExpandMoreIcon />}
|
||||
{listItemExpanded === index ? <ExpandLessIcon sx={{color: theme.palette.text.primary}} /> : <ExpandMoreIcon sx={{color: theme.palette.text.primary}}/>}
|
||||
</IconButton>
|
||||
</div>
|
||||
</ListItemText>
|
||||
@@ -1443,7 +1446,7 @@ const EnvironmentTab = memo((props) => {
|
||||
>
|
||||
<Tab
|
||||
value={0}
|
||||
label=<span>
|
||||
label=<span style={{color: theme.palette.text.secondary, }}>
|
||||
<img
|
||||
src="/icons/docker.svg"
|
||||
style={{ width: 20, height: 20, marginRight: 10, }}
|
||||
@@ -1452,7 +1455,7 @@ const EnvironmentTab = memo((props) => {
|
||||
/>
|
||||
<Tab
|
||||
value={1}
|
||||
label=<span>
|
||||
label=<span style={{color: theme.palette.text.secondary, }}>
|
||||
<img
|
||||
src="/icons/docker.svg"
|
||||
style={{ width: 20, height: 20, marginRight: 10,}}
|
||||
@@ -1461,23 +1464,23 @@ const EnvironmentTab = memo((props) => {
|
||||
/>
|
||||
<Tab
|
||||
value={2}
|
||||
label=<span>
|
||||
label=<span style={{color: theme.palette.text.secondary, }}>
|
||||
<img
|
||||
src="/icons/k8s.svg"
|
||||
style={{ width: 20, height: 20, marginRight: 10, }}
|
||||
style={{ width: 20, height: 20, marginRight: 10 }}
|
||||
/> k8s
|
||||
</span>
|
||||
/>
|
||||
</Tabs>
|
||||
<Typography variant="body1" color="textSecondary" style={{marginTop: 15, }}>
|
||||
{installationTab === 2 ?
|
||||
<span>
|
||||
<Typography variant='body2' color="textSecondary">
|
||||
Check our <a href="https://docs.docker.com/get-started/get-docker/" target="_blank" rel="noopener noreferrer" style={{textDecoration: "none", color: "#f85a3e",}}>Kubernetes documentation</a> for more information on how to run Shuffle on Kubernetes. The status of the node will change when connected.
|
||||
</span>
|
||||
</Typography>
|
||||
:
|
||||
<span>
|
||||
<Typography variant='body2' color="textSecondary">
|
||||
1. <a href="https://docs.docker.com/get-started/get-docker/" target="_blank" rel="noopener noreferrer" style={{textDecoration: "none", color: "#f85a3e",}}>Ensure Docker is installed</a> and the target server can reach '{globalUrl}'
|
||||
</span>
|
||||
</Typography>
|
||||
}
|
||||
|
||||
</Typography>
|
||||
@@ -1501,13 +1504,19 @@ const EnvironmentTab = memo((props) => {
|
||||
>
|
||||
<div style={{ display: "flex", position: "relative", }}>
|
||||
<code
|
||||
contenteditable="true"
|
||||
contentEditable="true"
|
||||
id="orborus_command"
|
||||
style={{
|
||||
// Wrap if larger than X
|
||||
whiteSpace: "pre-wrap",
|
||||
overflow: "auto",
|
||||
marginRight: 30,
|
||||
backgroundColor: themeMode === "dark" ? "#1e1e1e" : "#f5f5f5",
|
||||
color: themeMode === "dark" ? "#f8f8f2" : "#333",
|
||||
padding: "8px",
|
||||
borderRadius: "4px",
|
||||
fontFamily: "monospace",
|
||||
fontSize: 18,
|
||||
border: themeMode === "dark" ? "1px solid #555" : "1px solid #ddd",
|
||||
}}
|
||||
>
|
||||
{getOrborusCommand(environment)}
|
||||
@@ -1532,7 +1541,8 @@ const EnvironmentTab = memo((props) => {
|
||||
</div>
|
||||
|
||||
<Divider style={{marginTop: 25, marginBottom: 10, }}/>
|
||||
Configure HTTP Proxies: <Checkbox
|
||||
<div style={{display: 'flex', alignItems: 'center', }}>
|
||||
<Typography variant='body2' color="textSecondary">Configure HTTP Proxies:</Typography> <Checkbox
|
||||
id="shuffle_skip_proxies"
|
||||
onClick={() => {
|
||||
if (commandController.proxies === undefined) {
|
||||
@@ -1545,8 +1555,10 @@ const EnvironmentTab = memo((props) => {
|
||||
setUpdate(Math.random())
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
Disable Pipelines & Data Lake: <Checkbox
|
||||
<div style={{display: 'flex', alignItems: 'center', }}>
|
||||
<Typography variant='body2' color="textSecondary">Disable Pipelines & Data Lake:</Typography> <Checkbox
|
||||
id="shuffle_skip_pipelines"
|
||||
onClick={() => {
|
||||
if (commandController.pipelines === undefined) {
|
||||
@@ -1559,6 +1571,7 @@ const EnvironmentTab = memo((props) => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<Typography variant="body1" color="textSecondary" style={{marginTop: 15, }}>
|
||||
|
||||
@@ -43,7 +43,7 @@ import {
|
||||
|
||||
import Dropzone from "../components/Dropzone.jsx";
|
||||
import ShuffleCodeEditor from "../components/ShuffleCodeEditor1.jsx";
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
const Files = memo((props) => {
|
||||
@@ -58,6 +58,8 @@ const Files = memo((props) => {
|
||||
const [openEditor, setOpenEditor] = React.useState(false);
|
||||
const [renderTextBox, setRenderTextBox] = React.useState(false);
|
||||
const [loadFileModalOpen, setLoadFileModalOpen] = React.useState(false);
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
const [field1, setField1] = React.useState("");
|
||||
const [field2, setField2] = React.useState("");
|
||||
@@ -442,7 +444,7 @@ const Files = memo((props) => {
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#ff8544" }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: theme.palette.primary.main }}
|
||||
onClick={() => setLoadFileModalOpen(false)}
|
||||
color="primary"
|
||||
>
|
||||
@@ -450,7 +452,7 @@ const Files = memo((props) => {
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#1a1a1a", backgroundColor: "#ff8544" }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, }}
|
||||
disabled={downloadUrl.length === 0 || !downloadUrl.includes("http")}
|
||||
onClick={() => {
|
||||
handleGithubValidation();
|
||||
@@ -517,9 +519,9 @@ const Files = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<div style={{ color: "rgba(255,255,255,0.9)" }}>
|
||||
<Typography variant="h5" color="textPrimary" >
|
||||
Select sub-org to distribute files
|
||||
</div>
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
|
||||
<MenuItem value="none" onClick={()=> {handleSelectSubOrg(null, "none")}}>None</MenuItem>
|
||||
@@ -562,15 +564,14 @@ const Files = memo((props) => {
|
||||
|
||||
<div style={{ display: "flex", marginTop: 20 }}>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#ff8544" }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: theme.palette.primary.main }}
|
||||
onClick={() => setShowDistributionPopup(false)}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#1a1a1a", backgroundColor: "#ff8544", marginLeft: 10 }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, marginLeft: 10 }}
|
||||
onClick={() => {
|
||||
changeDistribution(fileIdSelectedForDistribution, selectedSubOrg);
|
||||
}}
|
||||
@@ -906,27 +907,27 @@ const Files = memo((props) => {
|
||||
onDrop={uploadFile}
|
||||
>
|
||||
{fileDistributionModal}
|
||||
<div style={{width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121',borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949", }}>
|
||||
<div style={{width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: theme.palette.platformColor,borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: theme.palette.defaultBorder, }}>
|
||||
|
||||
<div style={{height: "100%", maxHeight: 1700,overflowY: 'auto', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
||||
<div style={{height: "100%", maxHeight: 1700,overflowY: 'auto', scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin' }}>
|
||||
<DownloadFileIcon setLoadFileModalOpen={setLoadFileModalOpen} isSelectedFiles={isSelectedFiles} />
|
||||
|
||||
{fileDownloadModal}
|
||||
|
||||
<div style={{ marginTop: isSelectedFiles ? 2: 20, marginBottom:20 }}>
|
||||
<h2 style={{ display: isSelectedFiles ? null : "inline", marginTop: isSelectedFiles?0:null, marginBottom: isSelectedFiles?8:null, color: "#FFFFFF"}}>Files</h2>
|
||||
<span style={{ marginLeft: isSelectedFiles ? null : 25, color:isSelectedFiles?"#9E9E9E":null}}>
|
||||
<Typography variant="h5" color="textPrimary" style={{ display: isSelectedFiles ? null : "inline", marginTop: isSelectedFiles?0:null, marginBottom: isSelectedFiles?8:null, fontWeight: 500}}>Files</Typography>
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginLeft: isSelectedFiles ? null : 25,}}>
|
||||
Files from Workflows are a way to store as well as edit files.{" "}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://shuffler.io/docs/organizations#files"
|
||||
style={{ textDecoration: isSelectedFiles ? null:"none", color: isSelectedFiles? "#FF8444": "#f85a3e" }}
|
||||
style={{ textDecoration: isSelectedFiles ? null:"none", color: theme.palette.linkColor }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -937,7 +938,7 @@ const Files = memo((props) => {
|
||||
onClick={() => {
|
||||
upload.click();
|
||||
}}
|
||||
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,}}
|
||||
style={{ textTransform: 'none',fontSize: 16, borderRadius:isSelectedFiles?4:null, width:isSelectedFiles?143:null, height:isSelectedFiles?35:null, boxShadow: isSelectedFiles?'none':null,}}
|
||||
>
|
||||
Upload files
|
||||
</Button>
|
||||
@@ -958,9 +959,9 @@ const Files = memo((props) => {
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
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, }}
|
||||
style={{ marginLeft: 16, marginRight: 15, borderRadius:isSelectedFiles?4:null, width:isSelectedFiles?81:null, height:isSelectedFiles?35:null, boxShadow: isSelectedFiles?'none':null, }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
color="secondary"
|
||||
onClick={() => getFiles(selectedCategory)}
|
||||
>
|
||||
<CachedIcon />
|
||||
@@ -976,7 +977,6 @@ const Files = memo((props) => {
|
||||
labelId="input-namespace-select-label"
|
||||
id="input-namespace-select-id"
|
||||
style={{
|
||||
color: "white",
|
||||
minWidth: 122,
|
||||
maxWidth: 122,
|
||||
height: 35,
|
||||
@@ -1013,7 +1013,6 @@ const Files = memo((props) => {
|
||||
<MenuItem
|
||||
key={index}
|
||||
value={data}
|
||||
style={{ color: "white" }}
|
||||
>
|
||||
{data.replaceAll("_", " ")}
|
||||
</MenuItem>
|
||||
@@ -1044,8 +1043,8 @@ const Files = memo((props) => {
|
||||
Please note that your selected files ({selectedFileId?.length}) will be moved to the <kbd>{updateToThisCategory}</kbd> category.
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setShowFileCategoryPopup(false)} style={{fontSize: 16, textTransform: 'none'}}>Close</Button>
|
||||
<Button onClick={() => handleUpdateFileCategory(updateToThisCategory)} style={{fontSize: 16, textTransform: 'none', color: "#1a1a1a", backgroundColor: "#ff8544"}}>Update</Button>
|
||||
<Button onClick={() => setShowFileCategoryPopup(false)} style={{fontSize: 16, textTransform: 'none', color: theme.palette.primary.main }}>Close</Button>
|
||||
<Button variant="contained" color="primary" onClick={() => handleUpdateFileCategory(updateToThisCategory)} style={{fontSize: 16, textTransform: 'none', }}>Update</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</FormControl>
|
||||
@@ -1055,8 +1054,9 @@ const Files = memo((props) => {
|
||||
{renderTextBox ?
|
||||
<Tooltip title={"Close"} style={{}} aria-label={""}>
|
||||
<Button
|
||||
style={{ marginLeft: 5, marginRight: 15, height: 35, borderRadius: 4, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
|
||||
color="primary"
|
||||
style={{ marginLeft: 5, marginRight: 15, height: 35, borderRadius: 4, textTransform: 'none', fontSize: 16, }}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
setRenderTextBox(false);
|
||||
console.log(" close clicked")
|
||||
@@ -1068,8 +1068,9 @@ const Files = memo((props) => {
|
||||
:
|
||||
<Tooltip title={"Add new file category"} style={{}} aria-label={""}>
|
||||
<Button
|
||||
style={{ marginLeft: 5, marginRight: 15, width: 169, height: 35, borderRadius: 4, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
|
||||
color="primary"
|
||||
style={{whiteSpace: 'nowrap', textWrap: 'nowrap', marginLeft: 5, marginRight: 15, width: 169, height: 35, borderRadius: 4, textTransform: 'none', fontSize: 16, }}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
setRenderTextBox(true);
|
||||
}}
|
||||
@@ -1096,7 +1097,8 @@ const Files = memo((props) => {
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
height: 35,
|
||||
fontSize: 16,
|
||||
borderRadius: 4,
|
||||
@@ -1133,7 +1135,7 @@ const Files = memo((props) => {
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.defaultBorder,
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
@@ -1151,7 +1153,7 @@ const Files = memo((props) => {
|
||||
>
|
||||
<ListItem
|
||||
style={{
|
||||
borderBottom: "1px solid #494949" ,
|
||||
borderBottom: theme.palette.defaultBorder ,
|
||||
display: "table-row"
|
||||
}}
|
||||
>
|
||||
@@ -1198,7 +1200,7 @@ const Files = memo((props) => {
|
||||
padding: index === 0 ? "0px 8px 8px 15px" : "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle"
|
||||
}}
|
||||
primaryTypographyProps={{
|
||||
@@ -1215,7 +1217,7 @@ const Files = memo((props) => {
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "table-row",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
}}
|
||||
>
|
||||
{Array(8)
|
||||
@@ -1232,7 +1234,7 @@ const Files = memo((props) => {
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
height: "20px",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
@@ -1257,9 +1259,9 @@ const Files = memo((props) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bgColor = isSelectedFiles ? "#212121":"#27292d";
|
||||
var bgColor = themeMode === "dark" ? "#212121" : "#FFFFFF";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = isSelectedFiles ? "#1A1A1A":"#1f2023";
|
||||
bgColor = themeMode === "dark" ? "#1A1A1A" : "#EAEAEA";
|
||||
}
|
||||
const isDistributed = file?.suborg_distribution?.length > 0 ? true : false;
|
||||
const filenamesplit = file.filename.split(".")
|
||||
@@ -1425,9 +1427,20 @@ const Files = memo((props) => {
|
||||
readFileData(file)
|
||||
}}
|
||||
>
|
||||
<img src="/icons/editIcon.svg" alt="edit icon"
|
||||
style={{color: iseditable ? "white" : "grey", width: 24, height: 24}}
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.1038 4.66848C16.3158 4.45654 16.5674 4.28843 16.8443 4.17373C17.1212 4.05903 17.418 4 17.7177 4C18.0174 4 18.3142 4.05903 18.5911 4.17373C18.868 4.28843 19.1196 4.45654 19.3315 4.66848C19.5435 4.88041 19.7116 5.13201 19.8263 5.40891C19.941 5.68582 20 5.9826 20 6.28232C20 6.58204 19.941 6.87882 19.8263 7.15573C19.7116 7.43263 19.5435 7.68423 19.3315 7.89617L8.43807 18.7896L4 20L5.21038 15.5619L16.1038 4.66848Z"
|
||||
stroke={themeMode=== "dark" ? "#F1F1F1" : "#333"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
@@ -1470,15 +1483,39 @@ const Files = memo((props) => {
|
||||
downloadFile(file);
|
||||
}}
|
||||
>
|
||||
<img src="/icons/downloadIcon.svg" alt="download icon"
|
||||
style={{
|
||||
width: 24, height: 24,
|
||||
color:
|
||||
file.status === "active"
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
width="24"
|
||||
height="24"
|
||||
fill={themeMode === "dark" ? "#212121" : "#EDEDED"}
|
||||
fillOpacity="0.02"
|
||||
/>
|
||||
<path
|
||||
d="M8.22595 16.4463L11.7792 19.9995L15.3324 16.4463"
|
||||
stroke={file.status === "active" ? (themeMode === "dark" ? "#F1F1F1" : "black") : "grey"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M11.7792 12.0049V19.9997"
|
||||
stroke={file.status === "active" ? (themeMode === "dark" ? "#F1F1F1" : "black") : "grey"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M19.6676 17.415C20.4399 16.8719 21.019 16.0968 21.321 15.2023C21.6229 14.3078 21.632 13.3403 21.3468 12.4403C21.0617 11.5402 20.4971 10.7545 19.7352 10.197C18.9732 9.6396 18.0534 9.33948 17.1092 9.34021H15.99C15.7228 8.299 15.2229 7.33196 14.5279 6.5119C13.8329 5.69184 12.961 5.04013 11.9777 4.60583C10.9944 4.17153 9.92534 3.96596 8.85109 4.00459C7.77684 4.04322 6.72535 4.32505 5.77578 4.82886C4.82621 5.33267 4.00331 6.04534 3.36902 6.9132C2.73474 7.78106 2.30559 8.78151 2.11391 9.83922C1.92222 10.8969 1.97297 11.9844 2.26236 13.0196C2.55174 14.0549 3.07221 15.011 3.78459 15.816"
|
||||
stroke={file.status === "active" ? (themeMode === "dark" ? "#F1F1F1" : "black") : "grey"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
@@ -1496,7 +1533,31 @@ const Files = memo((props) => {
|
||||
toast(file.id + " copied to clipboard");
|
||||
}}
|
||||
>
|
||||
<img src="/icons/copyIcon.svg" alt="copy icon" style={{ color: "white", width: 24, height: 24 }} />
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
width="24"
|
||||
height="24"
|
||||
fillOpacity="1"
|
||||
/>
|
||||
<path
|
||||
d="M14 4H7.6C7.17565 4 6.76869 4.16857 6.46863 4.46863C6.16857 4.76869 6 5.17565 6 5.6V18.4C6 18.8243 6.16857 19.2313 6.46863 19.5314C6.76869 19.8314 7.17565 20 7.6 20H17.2C17.6243 20 18.0313 19.8314 18.3314 19.5314C18.6314 19.2313 18.8 18.8243 18.8 18.4V8.8L14 4Z"
|
||||
stroke={themeMode === "dark" ? "#F1F1F1" : "#333"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M14 4V8.8H18.8"
|
||||
stroke={themeMode === "dark" ? "#F1F1F1" : "#333"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
@@ -1570,7 +1631,6 @@ const Files = memo((props) => {
|
||||
disabled={userdata?.active_org?.role !== "admin" || (selectedOrganization.creator_org !== undefined && selectedOrganization.creator_org !== null && selectedOrganization.creator_org !== "" ) ? true : false}
|
||||
checked={isDistributed}
|
||||
style={{ }}
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
setShowDistributionPopup(true)
|
||||
if(file?.suborg_distribution?.length > 0){
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
import ReactGA from 'react-ga4';
|
||||
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import countries from "../components/Countries.jsx";
|
||||
import {
|
||||
Box,
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
import { Autocomplete } from "@mui/material";
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import {
|
||||
Cached as CachedIcon,
|
||||
ContentCopy as ContentCopyIcon,
|
||||
@@ -74,6 +74,9 @@ const LicencePopup = (props) => {
|
||||
const [errorMessage, setErrorMessage] = useState("")
|
||||
const [highlight, setHighlight] = useState(false)
|
||||
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
// Cloud
|
||||
const [calculatedApps, setCalculatedApps] = useState(600)
|
||||
const [calculatedCost, setCalculatedCost] = useState("$600")
|
||||
@@ -145,11 +148,12 @@ const LicencePopup = (props) => {
|
||||
padding: 20,
|
||||
paddingBottom: 30,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
height: "100%"
|
||||
height: "100%",
|
||||
|
||||
}
|
||||
|
||||
const userInScalePlan = userdata?.app_execution_limit > 10000
|
||||
const appRuns = userInScalePlan ? (userdata?.app_execution_limit / 1000) + "K App Runs" : userdata?.app_execution_limit === 10000 ? "10,000 App Runs" : "2,000 App Runs"
|
||||
const userInScalePlan = userdata?.app_execution_limit > 2000
|
||||
const appRuns = (userdata?.app_execution_limit / 1000) + "K App Runs"
|
||||
|
||||
// Add this function to format the limit value
|
||||
const formatLimit = (limit) => {
|
||||
@@ -277,7 +281,7 @@ const LicencePopup = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
console.log("selectedOrganization: ", selectedOrganization)
|
||||
|
||||
// Update the subscription features section
|
||||
billingInfo.subscription = {
|
||||
"active": true,
|
||||
@@ -480,7 +484,6 @@ const LicencePopup = (props) => {
|
||||
});
|
||||
}
|
||||
|
||||
console.log("OrgSyncFeatures: ", selectedOrganization?.sync_features)
|
||||
|
||||
const extraFeatures = Object.entries(features || {})
|
||||
.filter(([_, featureData]) => {
|
||||
@@ -503,9 +506,9 @@ const LicencePopup = (props) => {
|
||||
style={{ borderRadius: theme.palette?.borderRadius, }}
|
||||
placement="bottom"
|
||||
>
|
||||
<div style={{ backgroundColor: "#1e1e1e", border: "1.2px solid #ff8544", borderRadius: theme.palette?.borderRadius}}>
|
||||
<Paper
|
||||
style={newPaperstyle}
|
||||
<div style={{ backgroundColor: theme.palette.cardBackgroundColor, border: "1.2px solid #ff8544", borderRadius: theme.palette?.borderRadius}}>
|
||||
<div
|
||||
style={{ backgroundColor: theme.palette.cardBackgroundColor, ...newPaperstyle }}
|
||||
// onMouseEnter={() => setHovered(true)}
|
||||
// onMouseLeave={() => setHovered(false)}
|
||||
>
|
||||
@@ -591,9 +594,9 @@ const LicencePopup = (props) => {
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
{subscription.active === true && !isScale && <Button style={{ backgroundColor: '#2f2f2f', color: "#ffffff", textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', fontSize: 13 }}
|
||||
{subscription.active === true && !isScale && <Button style={{ textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', fontSize: 13 }}
|
||||
variant="contained"
|
||||
color="primary">
|
||||
color="secondary">
|
||||
Current Plan
|
||||
</Button>}
|
||||
<div style={{ display: "flex" }}>
|
||||
@@ -849,13 +852,12 @@ const LicencePopup = (props) => {
|
||||
<Button
|
||||
fullWidth
|
||||
color="primary"
|
||||
variant="contained"
|
||||
style={{
|
||||
marginTop: !userdata.has_card_available ? 25 : 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",
|
||||
|
||||
@@ -873,13 +875,13 @@ const LicencePopup = (props) => {
|
||||
</Button> ) : null}
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
style={{
|
||||
marginTop: isCloud? 10 : 30,
|
||||
borderRadius: 4,
|
||||
width: "100%",
|
||||
cursor: "pointer",
|
||||
textTransform: "capitalize",
|
||||
backgroundColor: "transparent",
|
||||
fontSize: 16,
|
||||
position: "relative", // Required for positioning tooltip
|
||||
}}
|
||||
@@ -922,7 +924,7 @@ const LicencePopup = (props) => {
|
||||
</span>
|
||||
</Button>
|
||||
|
||||
</Paper>
|
||||
</div>
|
||||
{/*
|
||||
<div style={{ paddingRight: 150, display: "flex", alignItems: "baseline" }}>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
|
||||
import {
|
||||
AppBar,
|
||||
Box,
|
||||
@@ -36,6 +37,7 @@ import AddIcon from '@mui/icons-material/Add';
|
||||
import Mousetrap from "mousetrap";
|
||||
import LicencePopup from "../components/LicencePopup.jsx";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import { getTheme } from "../theme.jsx";
|
||||
|
||||
const curpath = (typeof window !== "undefined" && window.location && typeof window.location.pathname === "string")
|
||||
? window.location.pathname
|
||||
@@ -118,18 +120,18 @@ const menuData = {
|
||||
label: "training_click"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Security Consultation",
|
||||
description:
|
||||
"Automate your infrastructure with expert guidance and tailored solutions.",
|
||||
icon: "/images/SecurityConsultation.svg",
|
||||
path: "/contact?category=security_consultation",
|
||||
gaData: {
|
||||
category: "navbar",
|
||||
action: "services_click",
|
||||
label: "security_consultation_click"
|
||||
}
|
||||
},
|
||||
// {
|
||||
// title: "Security Consultation",
|
||||
// description:
|
||||
// "Automate your infrastructure with expert guidance and tailored solutions.",
|
||||
// icon: "/images/SecurityConsultation.svg",
|
||||
// path: "/contact?category=security_consultation",
|
||||
// gaData: {
|
||||
// category: "navbar",
|
||||
// action: "services_click",
|
||||
// label: "security_consultation_click"
|
||||
// }
|
||||
// },
|
||||
],
|
||||
Resources: {
|
||||
columns: [
|
||||
@@ -751,7 +753,9 @@ const Navbar = (props) => {
|
||||
const topbar_var = "topbar_closed10"
|
||||
|
||||
const theme = useTheme();
|
||||
const {searchBarModalOpen, setSearchBarModalOpen, isDocSearchModalOpen} = useContext(Context)
|
||||
const {themeMode} = useContext(Context);
|
||||
const currentTheme = getTheme(themeMode);
|
||||
const {searchBarModalOpen, setSearchBarModalOpen, isDocSearchModalOpen, setIsDocSearchModalOpen} = useContext(Context)
|
||||
const [pricingModalOpen, setPricingModalOpen] = useState(false);
|
||||
const isTabletOrMobile = useMediaQuery(theme.breakpoints.down("lg"));
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
|
||||
@@ -772,7 +776,6 @@ const Navbar = (props) => {
|
||||
window.location.host === "shuffler.io" ||
|
||||
window.location.host === "localhost:5002";
|
||||
|
||||
|
||||
const stripeKey = typeof window === 'undefined' || window.location === undefined ? "" : window.location.origin === "https://shuffler.io" ? "pk_live_51PXYYMEJjT17t98N20qEqItyt1fLQjrnn41lPeG2PjnSlZHTDNKHuisAbW00s4KAn86nGuqB9uSVU4ds8MutbnMU00DPXpZ8ZD" : "pk_test_51PXYYMEJjT17t98NbDkojZ3DRvsFUQBs35LGMx3i436BXwEBVFKB9nCvHt0Q3M4MG3dz4mHheuWvfoYvpaL3GmsG00k1Rb2ksO"
|
||||
|
||||
useEffect(() => {
|
||||
@@ -853,24 +856,27 @@ const Navbar = (props) => {
|
||||
setSearchBarModalOpen(false);
|
||||
}}
|
||||
PaperProps={{
|
||||
style: {
|
||||
sx: {
|
||||
color: "white",
|
||||
minWidth: 750,
|
||||
height: 785,
|
||||
borderRadius: 16,
|
||||
minWidth: "750px",
|
||||
height: "785px",
|
||||
borderRadius: "16px",
|
||||
border: "1px solid var(--Container-Stroke, #494949)",
|
||||
background: "var(--Container, #000000)",
|
||||
background: currentTheme.palette.DialogStyle.backgroundColor,
|
||||
boxShadow: "0px 16px 24px 8px rgba(0, 0, 0, 0.25)",
|
||||
},
|
||||
'& .MuiDialogContent-root': {
|
||||
backgroundColor: currentTheme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
'& .MuiDialogTitle-root': {
|
||||
backgroundColor: currentTheme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
}}
|
||||
sx={{
|
||||
zIndex: 50005,
|
||||
'& .MuiBackdrop-root': {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", px: 2, pt: 2 }}>
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between",backgroundColor: currentTheme?.palette?.DialogStyle?.backgroundColor, alignItems: "center", px: 2, pt: 2 }}>
|
||||
<DialogTitle
|
||||
sx={{
|
||||
color: "var(--Paragraph-text, #C8C8C8)",
|
||||
@@ -893,7 +899,7 @@ const Navbar = (props) => {
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<DialogContent >
|
||||
<DialogContent style={{backgroundColor: currentTheme?.palette?.DialogStyle?.backgroundColor}} >
|
||||
<Box sx={{ pt: 3 }}>
|
||||
<SearchBox globalUrl={globalUrl} serverside={serverside} userdata={userdata} />
|
||||
</Box>
|
||||
@@ -974,6 +980,10 @@ const Navbar = (props) => {
|
||||
transform: "rotate(180deg)",
|
||||
},
|
||||
},
|
||||
// Add this to hide the ripple effect's container
|
||||
"& .MuiTouchRipple-root": {
|
||||
display: "none",
|
||||
},
|
||||
};
|
||||
|
||||
// Render menu content based on type
|
||||
@@ -1362,6 +1372,8 @@ const Navbar = (props) => {
|
||||
</Box>
|
||||
))}
|
||||
<Button
|
||||
component={Link}
|
||||
to="/pricing"
|
||||
sx={buttonStyles}
|
||||
onClick={() => {
|
||||
if(isCloud) {
|
||||
@@ -1380,6 +1392,8 @@ const Navbar = (props) => {
|
||||
Pricing
|
||||
</Button>
|
||||
<Button
|
||||
component={Link}
|
||||
to="/partners"
|
||||
sx={buttonStyles}
|
||||
onClick={() => {
|
||||
if(isCloud) {
|
||||
@@ -1451,10 +1465,12 @@ const Navbar = (props) => {
|
||||
useEffect(() => {
|
||||
Mousetrap.bind(['command+k', 'ctrl+k'], () => {
|
||||
setSearchBarModalOpen(true);
|
||||
setIsDocSearchModalOpen(false);
|
||||
return false; // Prevent the default action
|
||||
});
|
||||
Mousetrap.bind(['esc'], () => {
|
||||
setSearchBarModalOpen(false);
|
||||
setIsDocSearchModalOpen(false);
|
||||
return false; // Prevent the default action
|
||||
});
|
||||
|
||||
@@ -1537,9 +1553,10 @@ const Navbar = (props) => {
|
||||
const topbar = !isCloud || !showTopbar ? null :
|
||||
curpath === "/" || curpath.includes("/docs") || curpath === "/pricing" || curpath === "/contact" || curpath === "/search" || curpath === "/usecases" || curpath === "/training" || curpath === "/professional-services" ?
|
||||
<span style={{ zIndex: 50001, marginTop: -4}}>
|
||||
<div style={{ position: "relative", height: topbarHeight, backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", overflow: "hidden", }}>
|
||||
{/* uncommit this to show topbar for release */}
|
||||
{/* <div style={{ position: "relative", height: topbarHeight, backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", overflow: "hidden", }}>
|
||||
<Typography style={{ paddingTop: 7, fontSize:16, margin: "auto", textAlign: "center", color: "white", }}>
|
||||
{/* Shuffle 1.4.0 is out! Read more about */}
|
||||
// Shuffle 1.4.0 is out! Read more about
|
||||
Shuffle 2.0.0 is out now!
|
||||
<u>
|
||||
<span onClick={() => {
|
||||
@@ -1559,6 +1576,36 @@ const Navbar = (props) => {
|
||||
<IconButton color="secondary" style={{ position: "absolute", top: 0, right: 20, }} onClick={(event) => {
|
||||
setShowTopbar(false)
|
||||
|
||||
// Set storage that it's clicked
|
||||
localStorage.setItem(topbar_var, "true")
|
||||
}}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</div> */}
|
||||
{/* commit below div if we need to show release stuff */}
|
||||
<div style={{ position: "relative", height: topbarHeight, backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", overflow: "hidden", }}>
|
||||
<Typography style={{ paddingTop: 7, fontSize:16, margin: "auto", textAlign: "center", color: "white", }}>
|
||||
{/* Shuffle 1.4.0 is out! Read more about */}
|
||||
New
|
||||
<u>
|
||||
<span onClick={() => {
|
||||
ReactGA.event({
|
||||
category: "landingpage",
|
||||
action: "click_header_training",
|
||||
label: "",
|
||||
})
|
||||
|
||||
navigate("/training")
|
||||
|
||||
}} style={{ cursor: "pointer", textDecoration: "none", fontWeight: 600, color: "rgba(255,255,255,0.9)" }}>
|
||||
Public Training
|
||||
</span>
|
||||
</u>
|
||||
Dates Released!
|
||||
</Typography>
|
||||
<IconButton color="secondary" style={{ position: "absolute", top: 0, right: 20, }} onClick={(event) => {
|
||||
setShowTopbar(false)
|
||||
|
||||
// Set storage that it's clicked
|
||||
localStorage.setItem(topbar_var, "true")
|
||||
}}>
|
||||
@@ -1784,7 +1831,10 @@ const Navbar = (props) => {
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
|
||||
<IconButton
|
||||
sx={{ color: "white" }}
|
||||
onClick={() => setSearchBarModalOpen(true)}
|
||||
onClick={() => {
|
||||
setSearchBarModalOpen(true);
|
||||
setIsDocSearchModalOpen(false);
|
||||
}}
|
||||
>
|
||||
<SearchIcon sx={{ fontSize: 22 }} />
|
||||
</IconButton>
|
||||
@@ -1866,6 +1916,7 @@ const Navbar = (props) => {
|
||||
})
|
||||
}
|
||||
setSearchBarModalOpen(true);
|
||||
setIsDocSearchModalOpen(false);
|
||||
}}
|
||||
>
|
||||
<SearchIcon sx={{ fontSize: 24 }} />
|
||||
@@ -1910,6 +1961,7 @@ const Navbar = (props) => {
|
||||
padding: "8px 20px",
|
||||
"&:hover": {
|
||||
backgroundColor: "#494949",
|
||||
color: "white",
|
||||
border: "1px solid white",
|
||||
},
|
||||
}}
|
||||
@@ -2263,6 +2315,7 @@ const Navbar = (props) => {
|
||||
sx={{ width: 20, height: 20 }}
|
||||
/>
|
||||
<Typography sx={{
|
||||
color: "inherit",
|
||||
fontSize: '14px',
|
||||
fontFamily: theme.typography.fontFamily
|
||||
}}>
|
||||
@@ -2304,6 +2357,7 @@ const Navbar = (props) => {
|
||||
/>
|
||||
<Typography sx={{
|
||||
fontSize: '14px',
|
||||
color: "inherit",
|
||||
fontFamily: theme.typography.fontFamily
|
||||
}}>
|
||||
Settings
|
||||
@@ -2344,6 +2398,7 @@ const Navbar = (props) => {
|
||||
/>
|
||||
<Typography sx={{
|
||||
fontSize: '14px',
|
||||
color: "inherit",
|
||||
fontFamily: theme.typography.fontFamily
|
||||
}}>
|
||||
Notifications ({notifications === undefined || notifications === null ? 0 :
|
||||
@@ -2388,6 +2443,7 @@ const Navbar = (props) => {
|
||||
/>
|
||||
<Typography sx={{
|
||||
fontSize: '14px',
|
||||
color: "inherit",
|
||||
fontFamily: theme.typography.fontFamily
|
||||
}}>
|
||||
About
|
||||
@@ -2427,6 +2483,7 @@ const Navbar = (props) => {
|
||||
/>
|
||||
<Typography sx={{
|
||||
fontSize: '14px',
|
||||
color: "inherit",
|
||||
fontFamily: theme.typography.fontFamily
|
||||
}}>
|
||||
Logout
|
||||
@@ -2457,7 +2514,7 @@ const Navbar = (props) => {
|
||||
margin: 0
|
||||
}}
|
||||
>
|
||||
Version 1.4.5
|
||||
Version 2.0.2
|
||||
</Typography>
|
||||
</Box>
|
||||
</Menu>
|
||||
@@ -2503,6 +2560,7 @@ const Navbar = (props) => {
|
||||
})
|
||||
}
|
||||
setSearchBarModalOpen(true);
|
||||
setIsDocSearchModalOpen(false);
|
||||
}}
|
||||
>
|
||||
<SearchIcon sx={{ fontSize: 24 }} />
|
||||
@@ -2543,14 +2601,14 @@ const Navbar = (props) => {
|
||||
|
||||
{isCloud &&
|
||||
<Button
|
||||
variant="outlined"
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
sx={{
|
||||
...sharedButtonStyles,
|
||||
display: {
|
||||
xs: "none",
|
||||
lg: "block"
|
||||
},
|
||||
color: "white",
|
||||
backgroundColor: "#2F2F2F",
|
||||
border: "1px solid #2F2F2F",
|
||||
borderRadius: "8px",
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
|
||||
import React, { useRef, useState, useEffect, useLayoutEffect, useContext } from "react";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import { toast } from 'react-toastify';
|
||||
import { useParams, useNavigate, Link } from "react-router-dom";
|
||||
import theme from '../theme.jsx';
|
||||
import { getTheme } from '../theme.jsx';
|
||||
//import { useAlert
|
||||
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
@@ -112,6 +113,8 @@ const AuthenticationOauth2 = (props) => {
|
||||
authenticationType.client_secret !== null &&
|
||||
authenticationType.client_secret.length > 0
|
||||
);
|
||||
const {themeMode, brandColor} = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
const [clientId, setClientId] = React.useState(defaultConfigSet ? authenticationType.client_id : "");
|
||||
const [clientSecret, setClientSecret] = React.useState(defaultConfigSet ? authenticationType.client_secret : "");
|
||||
@@ -724,7 +727,7 @@ const AuthenticationOauth2 = (props) => {
|
||||
style={{ margin: 4, minHeight: 30, maxHeight: 30, borderRadius: theme.palette?.borderRadius, }}
|
||||
src={selectedAction.large_image}
|
||||
/>
|
||||
<Typography style={{ margin: 0, marginLeft: 10, marginTop: 5,}} variant="body1">
|
||||
<Typography style={{ margin: 0, marginLeft: 10, marginTop: 5, color: "#2f2f2f",}} variant="body1">
|
||||
One-click Login
|
||||
</Typography>
|
||||
</span>
|
||||
@@ -738,7 +741,7 @@ const AuthenticationOauth2 = (props) => {
|
||||
return (
|
||||
<div>
|
||||
<DialogTitle>
|
||||
<div style={{ color: "white" }}>
|
||||
<div style={{ color: theme.palette.text.primary }}>
|
||||
Authenticate {selectedApp.name.replaceAll("_", " ")}
|
||||
</div>
|
||||
</DialogTitle>
|
||||
@@ -749,7 +752,7 @@ const AuthenticationOauth2 = (props) => {
|
||||
target="_blank"
|
||||
rel="norefferer"
|
||||
href="/docs/apps#authentication"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
style={{ textDecoration: "none", color: theme.palette.linkColor}}
|
||||
>
|
||||
{" "}
|
||||
Learn more about Oauth2 with Shuffle
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import theme from "../theme.jsx";
|
||||
import React, { useEffect, useState, useContext } from "react";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import {
|
||||
Tooltip,
|
||||
TextField,
|
||||
@@ -69,6 +69,8 @@ const OrgHeader = (props) => {
|
||||
selectedOrganization.description
|
||||
);
|
||||
|
||||
const { themeMode } = useContext(Context)
|
||||
const {theme} = getTheme(themeMode)
|
||||
|
||||
const [file, setFile] = React.useState("");
|
||||
const [fileBase64, setFileBase64] = React.useState(
|
||||
@@ -364,10 +366,10 @@ const OrgHeader = (props) => {
|
||||
>
|
||||
<FormControl>
|
||||
<DialogTitle>
|
||||
<div style={{ color: "rgba(255, 255, 255, 0.9)" }}>Upload Organization Image</div>
|
||||
<div style={{ color: theme?.palette?.textColor}}>Upload Organization Image</div>
|
||||
</DialogTitle>
|
||||
{errorText}
|
||||
<DialogContent style={{ color: "rgba(255, 255, 255, 0.65)" }}>
|
||||
<DialogContent style={{ color: theme?.palette?.textColor }}>
|
||||
<AvatarEditor
|
||||
ref={setEditorRef}
|
||||
image={croppedData}
|
||||
@@ -389,7 +391,7 @@ const OrgHeader = (props) => {
|
||||
style={appIconStyle}
|
||||
onClick={() => { upload.click(); }}
|
||||
>
|
||||
<AddAPhotoOutlinedIcon style={{ color: "rgba(255, 255, 255, 0.9)" }} />
|
||||
<AddAPhotoOutlinedIcon style={{ color: theme?.palette?.textColor }} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="Zoom In">
|
||||
@@ -399,7 +401,7 @@ const OrgHeader = (props) => {
|
||||
style={appIconStyle}
|
||||
onClick={zoomIn}
|
||||
>
|
||||
<ZoomInOutlinedIcon style={{ color: "rgba(255, 255, 255, 0.9)" }} />
|
||||
<ZoomInOutlinedIcon style={{ color: theme?.palette?.textColor }} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="Zoom Out">
|
||||
@@ -409,7 +411,7 @@ const OrgHeader = (props) => {
|
||||
style={appIconStyle}
|
||||
onClick={zoomOut}
|
||||
>
|
||||
<ZoomOutOutlinedIcon style={{ color: "rgba(255, 255, 255, 0.9)" }} />
|
||||
<ZoomOutOutlinedIcon style={{ color: theme?.palette?.textColor }} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="Rotate">
|
||||
@@ -419,7 +421,7 @@ const OrgHeader = (props) => {
|
||||
style={appIconStyle}
|
||||
onClick={rotation}
|
||||
>
|
||||
<LoopIcon style={{ color: "rgba(255, 255, 255, 0.9)" }} />
|
||||
<LoopIcon style={{ color: theme?.palette?.textColor }} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
@@ -427,7 +429,7 @@ const OrgHeader = (props) => {
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", color: "rgba(255, 255, 255, 0.9)" }}
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", color: theme?.palette?.textColor }}
|
||||
onClick={onCancelSaveAppIcon}
|
||||
>
|
||||
Cancel
|
||||
@@ -491,7 +493,7 @@ const OrgHeader = (props) => {
|
||||
<div style={{ marginLeft: 16, alignContent: "center" }}>
|
||||
<div >
|
||||
<Button
|
||||
style={{ backgroundColor: '#ff8544', fontSize: 16, textTransform: 'capitalize', color: "#212121", boxShadow: "none", borderRadius: 4, width: 128, height: 40 }}
|
||||
style={{ fontSize: 16, textTransform: 'capitalize', boxShadow: "none", borderRadius: 4, width: 128, height: 40 }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
@@ -503,9 +505,9 @@ const OrgHeader = (props) => {
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
style={{ backgroundColor: '#494949', fontSize: 16, textTransform: 'capitalize', color: "#ffffff", boxShadow: "none", marginTop: 20, borderRadius: 4, width: 128, height: 40 }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
color="secondary"
|
||||
style={{ fontSize: 16, textTransform: 'capitalize', boxShadow: "none", marginTop: 20, borderRadius: 4, width: 128, height: 40 }}
|
||||
onClick={() => removeImage()}
|
||||
>
|
||||
Remove
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { memo, useEffect, useState } from "react";
|
||||
import React, { memo, useEffect, useState, useContext } from "react";
|
||||
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { toast } from "react-toastify"
|
||||
import theme from '../theme.jsx';
|
||||
import { getTheme } from '../theme.jsx';
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
//import { useAlert
|
||||
|
||||
import {
|
||||
@@ -89,6 +90,8 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
);
|
||||
|
||||
const [openNotification, setOpenNotification] = React.useState(false);
|
||||
const { themeMode, supportEmail, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
const handleStatusChange = (event) => {
|
||||
const { value } = event.target;
|
||||
@@ -178,7 +181,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
const [uploadRepo, setUploadRepo] = React.useState(selectedOrganization.defaults === undefined ? "" : selectedOrganization.defaults.workflow_upload_repo === undefined || selectedOrganization.defaults.workflow_upload_repo.length === 0 ? "" : selectedOrganization.defaults.workflow_upload_repo)
|
||||
const [uploadBranch, setUploadBranch] = React.useState(selectedOrganization.defaults === undefined ? defaultBranch : selectedOrganization.defaults.workflow_upload_branch === undefined || selectedOrganization.defaults.workflow_upload_branch.length === 0 ? defaultBranch : selectedOrganization.defaults.workflow_upload_branch)
|
||||
const [uploadUsername, setUploadUsername] = React.useState(selectedOrganization.defaults === undefined ? "" : selectedOrganization.defaults.workflow_upload_username === undefined || selectedOrganization.defaults.workflow_upload_username.length === 0 ? "" : selectedOrganization.defaults.workflow_upload_username)
|
||||
const [uploadToken, setUploadToken] = React.useState(selectedOrganization.defaults === undefined ? "" : selectedOrganization.defaults.workflow_upload_token === undefined || selectedOrganization.defaults.workflow_upload_token.length === 0 ? "" : selectedOrganization.defaults.workflow_upload_token)
|
||||
const [uploadToken, setUploadToken] = React.useState("")
|
||||
const [regionStatus, setRegionStatus] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -199,9 +202,10 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
setUploadUsername(selectedOrganization?.defaults?.workflow_upload_username)
|
||||
}
|
||||
|
||||
if (uploadToken !== selectedOrganization?.defaults?.workflow_upload_token) {
|
||||
setUploadToken(selectedOrganization?.defaults?.workflow_upload_token)
|
||||
}
|
||||
// Not showing the token in the UI (cause it's in plain text)
|
||||
// if (uploadToken !== selectedOrganization?.defaults?.workflow_upload_token) {
|
||||
// setUploadToken(selectedOrganization?.defaults?.workflow_upload_token)
|
||||
// }
|
||||
}, [selectedOrganization])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -264,7 +268,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
|
||||
const handleSendChangeRegionMail = (region) => {
|
||||
if (selectedOrganization === undefined || selectedOrganization === null) {
|
||||
toast.error("Failed to send request for changing region. Please contact support@shuffler.io.")
|
||||
toast.error(`Failed to send request for changing region. Please contact ${supportEmail}`)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -294,13 +298,13 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
body: JSON.stringify(data),
|
||||
}).then((response) => {
|
||||
if (response.status !== 200) {
|
||||
toast.error("Failed to send request for changing region. Please contact support@shuffler.io.")
|
||||
toast.error(`Failed to send request for changing region. Please contact ${supportEmail}`)
|
||||
} else {
|
||||
toast.success("Successfully sent request for region change. We will process the move and contact you shortly.")
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
toast.error("Failed to send request for changing region. Please contact support@shuffler.io.")
|
||||
toast.error(`Failed to send request for changing region. Please contact ${supportEmail}`)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -358,7 +362,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
const orgSaveButton = (
|
||||
<Tooltip title="Save any unsaved data" placement="bottom">
|
||||
<Button
|
||||
style={{ width: 244, height: 51, display: 'flex', justifyContent: 'center', textTransform: 'capitalize', padding: "16px, 24px, 16px, 24px", borderRadius: 4, backgroundColor: "#ff8544", color: "#1a1a1a", fontSize: 16, }}
|
||||
style={{ width: 244, height: 51, display: 'flex', justifyContent: 'center', textTransform: 'capitalize', padding: "16px, 24px, 16px, 24px", borderRadius: 4, fontSize: 16, }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={
|
||||
@@ -448,7 +452,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
<div style={{ marginTop: 8, display: "flex" }} />
|
||||
<div style={{ display: "flex" }}>
|
||||
<div style={{ width: "100%", maxWidth: 434, marginRight: 10 }}>
|
||||
Name
|
||||
<Typography variant="text" style={{color: theme.palette.text.primary}}>Name</Typography>
|
||||
<TextField
|
||||
required
|
||||
style={{
|
||||
@@ -459,7 +463,8 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
maxWidth: 434,
|
||||
marginTop: "5px",
|
||||
marginRight: "15px",
|
||||
backgroundColor: isEditOrgTab ? "#212121" : theme.palette.inputColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
placeholder="Name"
|
||||
@@ -513,10 +518,11 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
color="primary"
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
height: "35px",
|
||||
fontSize: "1em",
|
||||
borderRadius: 4,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
},
|
||||
classes: {
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
@@ -526,10 +532,10 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
</div>
|
||||
{userdata?.support ? (
|
||||
<div style={{ alignItems: 'center' }}>
|
||||
<div style={{ marginRight: '12px', color: 'white' }}>Status</div>
|
||||
<div style={{ marginRight: '12px', color: theme.palette.text.primary }}>Status</div>
|
||||
<FormControl style={{ width: 220, height: 35 }}>
|
||||
<Select
|
||||
style={{ minWidth: 220, marginTop: 5, maxWidth: 220, height: 35, borderRadius: 4 }}
|
||||
style={{ minWidth: 220, marginTop: 5, maxWidth: 220, height: 35, borderRadius: 4, color: theme.palette.textFieldStyle.color}}
|
||||
id="multiselect-status"
|
||||
multiple
|
||||
value={selectedStatus}
|
||||
@@ -552,13 +558,13 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
|
||||
{isCloud ? (
|
||||
<div style={{ marginLeft: 13, fontSize: 16, color: "#9E9E9E" }} >
|
||||
Change Region
|
||||
<Typography variant="text" style={{color: theme.palette.text.primary}}>Change Region</Typography>
|
||||
<RegionChangeModal selectedOrganization={selectedOrganization} setSelectedRegion={setSelectedRegion} userdata={userdata} handleSendChangeRegionMail={handleSendChangeRegionMail} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div style={{ marginTop: "10px" }} />
|
||||
About
|
||||
<Typography variant="text" style={{color: theme.palette.text.primary}}>Description</Typography>
|
||||
<div style={{ display: "flex" }}>
|
||||
<TextField
|
||||
required
|
||||
@@ -568,7 +574,8 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
flex: "1",
|
||||
marginTop: "5px",
|
||||
marginRight: "15px",
|
||||
backgroundColor: isEditOrgTab ? "#212121" : theme.palette.inputColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
height: 89,
|
||||
borderRadius: 4,
|
||||
}}
|
||||
@@ -621,7 +628,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
height: 89,
|
||||
borderRadius: 4,
|
||||
},
|
||||
@@ -632,7 +639,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<Typography variant="h5" style={{ color: "rgba(241, 241, 241, 1)", fontSize: 24, fontWeight: 600, marginTop: 40, textAlign: "left" }}>
|
||||
<Typography variant="h5" style={{ fontSize: 24, fontWeight: 500, marginTop: 40, textAlign: "left" }}>
|
||||
Preferences
|
||||
</Typography>
|
||||
|
||||
@@ -653,7 +660,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<span>
|
||||
<Typography style={{ fontWeight: 400, fontSize: 16 }}>Org Documentation reference</Typography>
|
||||
<Typography style={{ fontWeight: 400, fontSize: 18, color: theme.palette.text.primary }}>Org Documentation reference</Typography>
|
||||
|
||||
<Typography variant="body2" color="textSecondary" style={{ fontWeight: 400, fontSize: 16, marginTop: 8 }}>
|
||||
Add a URL that is added as a link, pointing to any external documentation page you want.
|
||||
@@ -668,7 +675,8 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
height: 35,
|
||||
fontSize: 16,
|
||||
borderRadius: 4,
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
type="name"
|
||||
@@ -709,6 +717,13 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
auto_provision: selectedOrganization?.sso_config?.auto_provision,
|
||||
}
|
||||
)
|
||||
|
||||
if (userdata.org_status.includes("integration_partner")) {
|
||||
toast.info("Reloading page to update the changes everywhere")
|
||||
setTimeout(() => {
|
||||
window.location.reload()
|
||||
}, 5000)
|
||||
}
|
||||
}
|
||||
}}
|
||||
onChange={(e) => {
|
||||
@@ -719,8 +734,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
borderRadius: 4,
|
||||
@@ -736,9 +750,9 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
serverside={false}
|
||||
/>
|
||||
<Grid item xs={12} style={{ marginTop: 20, }}>
|
||||
<Typography variant="h4" style={{ textAlign: "left", color: "rgba(241, 241, 241, 1)", fontSize: 24, fontWeight: 600, }}>Workflow Backup Repository</Typography>
|
||||
<Typography variant="body2" style={{ textAlign: "left", marginTop: 8, color: "#9E9E9E", fontSize: 16, fontWeight: 400 }}>
|
||||
Decide where workflows are backed up in a Git repository. Will create logs and notifications if upload fails. The repository and branch must already have been initialized. Files will show up in the repo root in the /orgId/workflow-status/workflowId.json format. <b>MSSP:</b> If suborg exists, this will automatically be applied for them as well (not retroactive). <a href="/docs/configuration#environment-variables" style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">Credentials are encrypted.</a>
|
||||
<Typography variant="h5" style={{ textAlign: "left", fontWeight: 500, }}>Workflow Backup Repository</Typography>
|
||||
<Typography variant="body2" style={{ textAlign: "left", marginTop: 8, color: theme.palette.text.secondary, fontSize: 16, fontWeight: 400 }}>
|
||||
Decide where workflows are backed up in a Git repository. Will create logs and notifications if upload fails. The repository and branch must already have been initialized. Files will show up in the repo root in the /orgId/workflow-status/workflowId.json format. <b>MSSP:</b> If suborg exists, this will automatically be applied for them as well (not retroactive). <a href="/docs/configuration#environment-variables" style={{ textDecoration: "none", color: theme.palette.linkColor }} target="_blank">Credentials are encrypted.</a>
|
||||
</Typography>
|
||||
<Grid container style={{ marginTop: 10, }} spacing={2}>
|
||||
<Grid item xs={6} style={{}}>
|
||||
@@ -751,7 +765,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
marginTop: "8px",
|
||||
marginRight: "16px",
|
||||
height: 35,
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
type="name"
|
||||
@@ -770,7 +784,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
@@ -791,7 +805,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
marginTop: "8px",
|
||||
marginRight: "16px",
|
||||
height: 35,
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
type="name"
|
||||
@@ -810,7 +824,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
@@ -833,7 +847,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
marginTop: "8px",
|
||||
marginRight: "16px",
|
||||
height: 35,
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
type="name"
|
||||
@@ -852,8 +866,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
borderRadius: 4,
|
||||
@@ -865,7 +878,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
</Grid>
|
||||
<Grid item xs={6} style={{}}>
|
||||
<span>
|
||||
<Typography style={{ fontWeight: 400, fontSize: 16 }}>Git token/password</Typography>
|
||||
<Typography style={{ fontWeight: 400, fontSize: 16 }}>New Git token/password</Typography>
|
||||
<TextField
|
||||
required
|
||||
style={{
|
||||
@@ -873,7 +886,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
marginTop: "8px",
|
||||
marginRight: "16px",
|
||||
height: 35,
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
id="outlined-with-placeholder"
|
||||
@@ -891,7 +904,7 @@ const OrgHeaderexpandedNew = (props) => {
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
@@ -1116,7 +1129,7 @@ const RegionChangeModal = memo(({ selectedOrganization, setSelectedRegion, userd
|
||||
} else if (regiontag === "ca") {
|
||||
regiontag = "CA";
|
||||
regionCode = "ca";
|
||||
} else if (regiontag === "austrailia") {
|
||||
} else if (regiontag === "au") {
|
||||
regiontag = "AUS";
|
||||
regionCode = "au"
|
||||
}
|
||||
@@ -1146,9 +1159,6 @@ const RegionChangeModal = memo(({ selectedOrganization, setSelectedRegion, userd
|
||||
selectedOrganization.region = "europe-west2";
|
||||
}
|
||||
|
||||
if (region === "AUS") {
|
||||
region = "AUS (test)"
|
||||
}
|
||||
|
||||
// Check if the current region matches the selected region
|
||||
if (region === selectedOrganization.region) {
|
||||
@@ -1157,7 +1167,7 @@ const RegionChangeModal = memo(({ selectedOrganization, setSelectedRegion, userd
|
||||
<MenuItem value={region} key={index} disabled>
|
||||
{/* show region image through cdn */}
|
||||
<img src={`https://flagcdn.com/48x36/${regionImageCode}.png`} alt={region} style={{ marginRight: 10 }} />
|
||||
{region}
|
||||
{region === "AUS" ? "AUS (test)" : region}
|
||||
</MenuItem>
|
||||
);
|
||||
} else {
|
||||
@@ -1167,7 +1177,7 @@ const RegionChangeModal = memo(({ selectedOrganization, setSelectedRegion, userd
|
||||
alt={region}
|
||||
style={{ marginRight: 10, width: 20, height: 18, }}
|
||||
/>
|
||||
{region}
|
||||
{region === "AUS" ? "AUS (test)" : region}
|
||||
</MenuItem>;
|
||||
}
|
||||
})}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import React, { useEffect, useState, useCallback, useContext } from 'react';
|
||||
import { Link, useNavigate, useLocation } from "react-router-dom";
|
||||
import Billing from "../components/Billing.jsx";
|
||||
import Priorities from "../components/Priorities.jsx";
|
||||
@@ -8,7 +8,8 @@ import CloudSyncTab from '../components/CloudSyncTab.jsx';
|
||||
import SSOTab from "../components/ssoTab.jsx"
|
||||
import { ToastContainer, toast } from "react-toastify";
|
||||
import { Button, Tooltip } from '@mui/material';
|
||||
|
||||
import { getTheme } from '../theme.jsx';
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
const OrganizationTab = (props) => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
@@ -25,7 +26,9 @@ const OrganizationTab = (props) => {
|
||||
selectedOrganization, handleGetOrg,
|
||||
handleStatusChange, handleEditOrg,
|
||||
isLoaded,
|
||||
removeCookie
|
||||
removeCookie,
|
||||
isIntegrationPartner, isChildOrg,
|
||||
isGlobalUser
|
||||
} = props;
|
||||
|
||||
const [selectedTab, setSelectedTab] = useState('org_config');
|
||||
@@ -33,10 +36,28 @@ const OrganizationTab = (props) => {
|
||||
const [billingInfo, setBillingInfo] = useState({});
|
||||
const [orgRequest, setOrgRequest] = React.useState(true);
|
||||
const [curIndex, setCurIndex] = React.useState(0);
|
||||
const items = ['Org Configuration', "SSO", "Notifications", 'Billing & Stats', 'Branding'];
|
||||
const [visibleTabs, setVisibleTabs] = useState(items);
|
||||
const [unreadNotifications, setUnreadNotifications] = React.useState(
|
||||
notifications?.filter((notification) => notification.read === false)?.length
|
||||
);
|
||||
|
||||
const { themeMode, brandColor, brandName } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (isIntegrationPartner && isChildOrg && !isGlobalUser) {
|
||||
setVisibleTabs(items.filter((item) => item !== 'Branding' && item !== 'SSO'));
|
||||
}else {
|
||||
if (userdata && userdata.active_org && userdata.active_org.role === 'admin') {
|
||||
setVisibleTabs(items);
|
||||
}else {
|
||||
setVisibleTabs(items.filter((item) => item !== 'SSO'));
|
||||
}
|
||||
}
|
||||
},[isIntegrationPartner, isChildOrg, isGlobalUser, userdata]);
|
||||
|
||||
useEffect(() => {
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
const tabName = queryParams.get('admin_tab');
|
||||
@@ -48,10 +69,26 @@ const OrganizationTab = (props) => {
|
||||
} else if(decodedTabName === 'sso'){
|
||||
setCurIndex(1)
|
||||
}else if (decodedTabName === 'notifications' || decodedTabName === 'priorities') {
|
||||
if (isIntegrationPartner && isChildOrg && !isGlobalUser) {
|
||||
setCurIndex(1);
|
||||
}else {
|
||||
if (userdata && userdata.active_org && userdata.active_org.role === 'admin') {
|
||||
setCurIndex(2);
|
||||
}else {
|
||||
setCurIndex(1);
|
||||
}
|
||||
}
|
||||
} else if (decodedTabName === 'billingstats' || decodedTabName === 'billing') {
|
||||
if (isIntegrationPartner && isChildOrg && !isGlobalUser) {
|
||||
setCurIndex(2);
|
||||
} else {
|
||||
if (userdata && userdata?.active_org && userdata?.active_org?.role === 'admin') {
|
||||
setCurIndex(3);
|
||||
} else if (decodedTabName === 'branding(beta)') {
|
||||
} else {
|
||||
setCurIndex(2);
|
||||
}
|
||||
}
|
||||
} else if (decodedTabName === 'branding') {
|
||||
setCurIndex(4);
|
||||
}
|
||||
// else if (decodedTabName === 'analytics') {
|
||||
@@ -64,7 +101,7 @@ const OrganizationTab = (props) => {
|
||||
const formattedTabName = tabName.toLowerCase().replace(/[\s&]+/g, '');
|
||||
const encodedTabName = encodeURIComponent(formattedTabName);
|
||||
setSelectedTab(formattedTabName);
|
||||
document.title = `Shuffle - admin - ${formattedTabName}`;
|
||||
document.title = brandName?.length > 0 ? `${brandName} - admin - ${formattedTabName}` : `Shuffle - admin - ${formattedTabName}`;
|
||||
navigate(`?admin_tab=${encodedTabName}`);
|
||||
};
|
||||
|
||||
@@ -137,10 +174,11 @@ const OrganizationTab = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div style={{ height: "100%", width: "100%", color: '#FFFFFF', backgroundColor: '#212121', borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949", boxSizing: 'border-box' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-around', width: "100%", borderBottom: '1px solid #494949' ,boxSizing: 'border-box' }}>
|
||||
{['Org Configuration', "sso", "Notifications", 'Billing & Stats', 'Branding'].map((tabName, index) => (
|
||||
<div style={{ height: "100%", width: "100%", color: theme.palette.platformColor, backgroundColor: theme.palette.platformColor, borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: theme.palette.defaultBorder, boxSizing: 'border-box' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-around', width: "100%", borderBottom: theme.palette.defaultBorder ,boxSizing: 'border-box' }}>
|
||||
{visibleTabs.map((tabName, index) => (
|
||||
<Tooltip
|
||||
key={index}
|
||||
title={
|
||||
@@ -161,10 +199,10 @@ const OrganizationTab = (props) => {
|
||||
sx={{
|
||||
"&.MuiButton-root": {
|
||||
padding: '28px 0',
|
||||
borderBottom: index === curIndex ? '2px solid #FF8444' : 'none',
|
||||
borderBottom: index === curIndex ? `2px solid ${theme.palette.primary.main}`: 'none',
|
||||
cursor: 'pointer',
|
||||
fontWeight: index === curIndex ? 'bold' : 'normal',
|
||||
color: index === curIndex ? "#FF8444" : "#FFFFFF",
|
||||
color: index === curIndex ? theme.palette.primary.main : theme.palette.text.primary,
|
||||
textTransform: 'none',
|
||||
fontSize: 16,
|
||||
width: "100%",
|
||||
@@ -172,7 +210,7 @@ const OrganizationTab = (props) => {
|
||||
borderRadius: 0,
|
||||
},
|
||||
"&: hover": {
|
||||
backgroundColor: "#323232"
|
||||
backgroundColor: theme.palette.hoverColor
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
color: "#6F6F6F",
|
||||
@@ -182,7 +220,7 @@ const OrganizationTab = (props) => {
|
||||
((tabName === "sso")) && !(userdata?.support || userdata?.active_org?.role === "admin")
|
||||
}
|
||||
>
|
||||
{index === 2 && unreadNotifications > 0 ? (
|
||||
{tabName.toLowerCase() === "notifications" && unreadNotifications > 0 ? (
|
||||
<div style={{ position: 'relative' }}>
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
@@ -191,7 +229,7 @@ const OrganizationTab = (props) => {
|
||||
width: 20,
|
||||
height: 20,
|
||||
borderRadius: 10,
|
||||
backgroundColor: '#FF8444',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: '#FFFFFF',
|
||||
fontSize: 12,
|
||||
display: 'flex',
|
||||
@@ -203,7 +241,7 @@ const OrganizationTab = (props) => {
|
||||
{tabName}
|
||||
</div>
|
||||
) : (
|
||||
<>{index === 1 ? "SSO" : tabName}</>
|
||||
<>{tabName}</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect, useLayoutEffect, useMemo } from "react";
|
||||
import React, { useState, useEffect, useContext, useMemo } from "react";
|
||||
import { toast } from 'react-toastify';
|
||||
import { makeStyles, createStyles } from "@mui/styles";
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
|
||||
import { useNavigate, Link, useParams } from "react-router-dom";
|
||||
import { validateJson, GetIconInfo } from "../views/Workflows.jsx";
|
||||
@@ -11,7 +11,7 @@ import { NestedMenuItem } from "mui-nested-menu";
|
||||
import { parsedDatatypeImages } from "../components/AppFramework.jsx";
|
||||
import { green, yellow, red } from "../views/AngularWorkflow.jsx"
|
||||
//import { useAlert
|
||||
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import {
|
||||
Chip,
|
||||
ButtonGroup,
|
||||
@@ -215,6 +215,9 @@ const ParsedAction = (props) => {
|
||||
}
|
||||
}, [expansionModalOpen])
|
||||
|
||||
const {themeMode, supportEmail} = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
/*
|
||||
useEffect(() => {
|
||||
// This will have the OLD selectedAction, not the new one huh?
|
||||
@@ -1626,7 +1629,7 @@ const ParsedAction = (props) => {
|
||||
padding: 8,
|
||||
paddingLeft: 14,
|
||||
paddingBottom: 4,
|
||||
backgroundColor: hover ? theme.palette.surfaceColor : theme.palette.inputColor,
|
||||
backgroundColor: hover ? theme.palette.hoverColor : theme.palette.textFieldStyle.backgroundColor,
|
||||
}} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
|
||||
onClick={(event) => {
|
||||
// event.preventDefault()
|
||||
@@ -1664,7 +1667,7 @@ const ParsedAction = (props) => {
|
||||
<span style={{ marginBottom: 0, marginTop: 3, }}>{newActionname}</span>
|
||||
</div>
|
||||
{extraDescription.length > 0 ?
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginTop: 0, overflow: "hidden", whiteSpace: "nowrap", display: "block", }}>
|
||||
<Typography variant="body2" style={{ marginTop: 0, overflow: "hidden", whiteSpace: "nowrap", display: "block", color: theme.palette.textPrimary}}>
|
||||
{extraDescription}
|
||||
</Typography>
|
||||
: null}
|
||||
@@ -1738,14 +1741,14 @@ const ParsedAction = (props) => {
|
||||
}}
|
||||
>
|
||||
<Tooltip title={"App: " + selectedAction.app_name + ". Click to open in new tab"} placement="top">
|
||||
<a href={"/apps/" + selectedAction?.app_id} target="_blank" style={{ textDecoration: "none", color: "white", }}>
|
||||
<a href={"/apps/" + selectedAction?.app_id} target="_blank" style={{ textDecoration: "none", color: theme.palette.textPrimary, }}>
|
||||
<img src={selectedAppIcon} style={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginRight: 10,
|
||||
borderRadius: 5,
|
||||
marginTop: 13,
|
||||
border: "2px solid rgba(255,255,255,0.3)",
|
||||
border: themeMode === "dark" ? "2px solid rgba(255,255,255,0.3)" : "2px solid rgba(0, 0, 0, 0.1)",
|
||||
}} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
@@ -1809,7 +1812,7 @@ const ParsedAction = (props) => {
|
||||
title="See previous results for this action"
|
||||
placement="top"
|
||||
>
|
||||
<ArrowLeftIcon style={{ color: "rgba(255,255,255,0.7)" }} />
|
||||
<ArrowLeftIcon style={{ color: theme.palette.textPrimary }} />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
<IconButton
|
||||
@@ -1829,7 +1832,7 @@ const ParsedAction = (props) => {
|
||||
title="Find app documentation"
|
||||
placement="top"
|
||||
>
|
||||
<DescriptionIcon style={{ color: "rgba(255,255,255,0.7)" }} />
|
||||
<DescriptionIcon style={{ color: theme.palette.textPrimary }} />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
|
||||
@@ -1863,7 +1866,7 @@ const ParsedAction = (props) => {
|
||||
{autoCompleting ?
|
||||
<CircularProgress style={{ height: 20, width: 20, }} />
|
||||
:
|
||||
<AutoFixHighIcon style={{ color: "rgba(255,255,255,0.7)", height: 24, }} />
|
||||
<AutoFixHighIcon style={{ color: theme.palette.textPrimary, height: 24, }} />
|
||||
}
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
@@ -1883,7 +1886,7 @@ const ParsedAction = (props) => {
|
||||
marginTop: "auto",
|
||||
marginBottom: "auto",
|
||||
height: 30,
|
||||
marginLeft: 115,
|
||||
marginLeft: 98,
|
||||
textTransform: "none",
|
||||
}}
|
||||
disabled={autoCompleting}
|
||||
@@ -1891,7 +1894,7 @@ const ParsedAction = (props) => {
|
||||
if (runFromHere !== undefined) {
|
||||
runFromHere(selectedAction)
|
||||
} else {
|
||||
toast.error("Function not available. Please contact support@shuffler.io")
|
||||
toast.error(`Function not available. Please contact ${supportEmail}`)
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -1939,6 +1942,12 @@ const ParsedAction = (props) => {
|
||||
<Select
|
||||
MenuProps={{
|
||||
disableScrollLock: true,
|
||||
PaperProps: {
|
||||
sx: {
|
||||
"&. MuiList-root": {
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
}
|
||||
}}
|
||||
}}
|
||||
value={selectedAction.app_version}
|
||||
onChange={(event) => {
|
||||
@@ -1963,9 +1972,8 @@ const ParsedAction = (props) => {
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 10, right: 10,
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
height: 35,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
}}
|
||||
@@ -1978,9 +1986,12 @@ const ParsedAction = (props) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={index}
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
sx={{
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor,
|
||||
},
|
||||
}}
|
||||
value={data.version}
|
||||
>
|
||||
@@ -1994,12 +2005,16 @@ const ParsedAction = (props) => {
|
||||
</div>
|
||||
<div style={{ display: "flex" }}>
|
||||
<div style={{ flex: 5 }}>
|
||||
<Typography style={{ color: "rgba(255,255,255,0.7)" }}>Name</Typography>
|
||||
<Typography style={{ color: theme.palette.textPrimary,}}>Name</Typography>
|
||||
<TextField
|
||||
style={theme.palette.textFieldStyle}
|
||||
InputProps={{
|
||||
style: theme.palette.innerTextfieldStyle,
|
||||
disableUnderline: true,
|
||||
style: {
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
height: 40,
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
@@ -2218,10 +2233,10 @@ const ParsedAction = (props) => {
|
||||
placement="top"
|
||||
>
|
||||
<span>
|
||||
<Typography style={{ color: "rgba(255,255,255,0.7)" }}>Delay</Typography>
|
||||
<Typography style={{ color: theme.palette.textPrimary }}>Delay</Typography>
|
||||
<TextField
|
||||
InputProps={{
|
||||
style: theme.palette.innerTextfieldStyle,
|
||||
style: theme.palette.textFieldStyle,
|
||||
disableUnderline: true,
|
||||
}}
|
||||
disabled={selectedAction?.parent_controlled === true && workflow?.parentorg_workflow?.length > 0}
|
||||
@@ -2280,7 +2295,7 @@ const ParsedAction = (props) => {
|
||||
|
||||
<div style={{ marginTop: 15, position: "relative", }}>
|
||||
<div style={{display: "flex", }}>
|
||||
<Typography style={{ color: "rgba(255,255,255,0.7)", flex: 10, }}>
|
||||
<Typography style={{ color: theme.palette.textPrimary, flex: 10, }}>
|
||||
Authentication
|
||||
</Typography>
|
||||
|
||||
@@ -2333,7 +2348,7 @@ const ParsedAction = (props) => {
|
||||
title={
|
||||
workflow?.suborg_distribution?.length > 0 && Object.getOwnPropertyNames(selectedAction?.selectedAuthentication).length !== 0 ? (
|
||||
<React.Fragment>
|
||||
<div style={{padding: 10, backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius, border: "1px solid rgba(255,255,255,0)"}}>
|
||||
<div style={{padding: 10, backgroundColor: theme.palette.textFieldStyle.backgroundColor, borderRadius: theme.palette.borderRadius, border: theme.palette.defaultBorder}}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
@@ -2351,10 +2366,18 @@ const ParsedAction = (props) => {
|
||||
</React.Fragment>
|
||||
) : null
|
||||
} placement="left">
|
||||
<div style={{ display: "flex" }}>
|
||||
<div style={{ display: "flex", }}>
|
||||
<Select
|
||||
MenuProps={{
|
||||
disableScrollLock: true,
|
||||
PaperProps: {
|
||||
sx: {
|
||||
'& .MuiList-root': {
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
labelId="select-app-auth"
|
||||
value={
|
||||
@@ -2436,17 +2459,20 @@ const ParsedAction = (props) => {
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
height: 35,
|
||||
maxWidth: rightsidebarStyle.maxWidth - 80,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
}}
|
||||
>
|
||||
<MenuItem
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
sx={{
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.textFieldStyle.hoverBackgroundColor, // you define this in your theme
|
||||
},
|
||||
}}
|
||||
value="No selection"
|
||||
>
|
||||
@@ -2460,11 +2486,14 @@ const ParsedAction = (props) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={data.id}
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
sx={{
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
maxWidth: 500,
|
||||
overflowX: "auto",
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.hoverColor
|
||||
},
|
||||
}}
|
||||
value={data}
|
||||
>
|
||||
@@ -2472,7 +2501,7 @@ const ParsedAction = (props) => {
|
||||
{data?.validation?.valid === true ?
|
||||
<Tooltip title="Authentication has been validated" placement="top">
|
||||
<Chip
|
||||
style={{ marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", borderColor: green, maxHeight: 25, }}
|
||||
style={{ marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", borderColor: green, maxHeight: 25, color: theme.palette.chipStyle.color, backgroundColor: theme.palette.chipStyle.backgroundColor }}
|
||||
label={"Valid"}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
@@ -2481,7 +2510,7 @@ const ParsedAction = (props) => {
|
||||
: null}
|
||||
{data?.last_modified === true ?
|
||||
<Chip
|
||||
style={{ marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", maxHeight: 25, }}
|
||||
style={{ marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", maxHeight: 25, color: theme.palette.chipStyle.color, backgroundColor: theme.palette.chipStyle.backgroundColor }}
|
||||
label={"Latest"}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
@@ -2503,9 +2532,12 @@ const ParsedAction = (props) => {
|
||||
<Divider style={{ marginTop: 10, marginBottom: 10, }} />
|
||||
|
||||
<MenuItem
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
sx={{
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textPrimary,
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.hoverColor
|
||||
},
|
||||
}}
|
||||
value="authgroups"
|
||||
disabled
|
||||
@@ -2637,7 +2669,7 @@ const ParsedAction = (props) => {
|
||||
|
||||
{workflow.execution_variables !== undefined && workflow.execution_variables !== null && workflow.execution_variables.length > 0 ? (
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
<Typography color="textSecondary">Runtime variable (optional)</Typography>
|
||||
<Typography style={{color: theme.palette.textPrimary}}>Runtime variable (optional)</Typography>
|
||||
<Select
|
||||
MenuProps={{
|
||||
disableScrollLock: true,
|
||||
@@ -2742,8 +2774,8 @@ const ParsedAction = (props) => {
|
||||
options={renderedActionOptions}
|
||||
ListboxProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
color: theme.palette.textColor,
|
||||
},
|
||||
}}
|
||||
filterOptions={(options, { inputValue }) => {
|
||||
@@ -2774,7 +2806,7 @@ const ParsedAction = (props) => {
|
||||
}}
|
||||
|
||||
style={{
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
backgroundColor: theme.palette.cardBackgroundColor,
|
||||
height: 35,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
}}
|
||||
@@ -2890,7 +2922,8 @@ const ParsedAction = (props) => {
|
||||
const actionDescription = null
|
||||
|
||||
return (
|
||||
<Tooltip title={actionDescription}
|
||||
<Tooltip
|
||||
title={actionDescription}
|
||||
placement="right"
|
||||
open={!hiddenDescription}
|
||||
PopperProps={{
|
||||
@@ -2913,13 +2946,18 @@ const ParsedAction = (props) => {
|
||||
dataLPIgnore="true"
|
||||
autoComplete="off"
|
||||
|
||||
color="primary"
|
||||
|
||||
id="checkbox-search"
|
||||
variant="body1"
|
||||
style={{
|
||||
...theme.palette.textFieldStyle,
|
||||
border: selectedAction?.parent_controlled === true && workflow?.parentorg_workflow?.length > 0 ? `1px dotted ${theme.palette.distributionColor}` : "inherit",
|
||||
}}
|
||||
inputProps={{
|
||||
...params.inputProps,
|
||||
style: {
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
}}
|
||||
label={isIntegration ? "Choose a category" : "Find Actions"}
|
||||
variant="outlined"
|
||||
name={`disable_autocomplete_${Math.random()}`}
|
||||
@@ -2933,12 +2971,12 @@ const ParsedAction = (props) => {
|
||||
|
||||
{selectedAction?.app_name === "Shuffle AI" && selectedAction?.name === "run_llm" ?
|
||||
selectedAction?.environment === "Cloud" && isCloud ? (
|
||||
<Typography color="textSecondary" variant="body2" style={{ paddingTop: 25, }}>
|
||||
<Typography variant="body2" style={{color: theme.palette.textPrimary, paddingTop: 25, }}>
|
||||
Info: Cloud Inference processing runs with Shuffle's GPUs in EU, Netherlands, and may be unstable. Your data is NOT stored there.
|
||||
</Typography>
|
||||
)
|
||||
:
|
||||
<Typography color="textSecondary" variant="body2" style={{ paddingTop: 25, color: red, }}>
|
||||
<Typography variant="body2" style={{ paddingTop: 25, color: red, color: theme.palette.textPrimary}}>
|
||||
This action is slow without GPU's. Use Shuffle's Cloud Runtime location for faster processing.
|
||||
</Typography>
|
||||
:
|
||||
@@ -2959,7 +2997,6 @@ const ParsedAction = (props) => {
|
||||
apps !== undefined && apps !== null && apps.length > 0 ?
|
||||
<div style={{ display: "flex", maxWidth: 335, overflowX: "auto", overflowY: "hidden", }}>
|
||||
<div onClick={() => {
|
||||
|
||||
selectedAction.example = "noapp"
|
||||
selectedAction.large_image = newimage
|
||||
if (cy !== undefined && cy !== null) {
|
||||
@@ -3029,7 +3066,13 @@ const ParsedAction = (props) => {
|
||||
|
||||
var found = false
|
||||
for (var key in app.categories) {
|
||||
if (app.categories[key].toLowerCase() !== newactionname) {
|
||||
|
||||
var localnewactionname = newactionname
|
||||
if (newactionname == "comms") {
|
||||
localnewactionname = "communication"
|
||||
}
|
||||
|
||||
if (app.categories[key].toLowerCase() !== localnewactionname) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -3042,6 +3085,9 @@ const ParsedAction = (props) => {
|
||||
}
|
||||
|
||||
var isAppSelected = false
|
||||
|
||||
console.log("App found: ", app.name, app.categories, appIndex, newactionname)
|
||||
|
||||
const paramIndex = selectedAction.parameters.findIndex((param) => param.name === "app_name")
|
||||
if (paramIndex > -1) {
|
||||
// Check the actual value and if it's the same
|
||||
@@ -3794,8 +3840,8 @@ const ParsedAction = (props) => {
|
||||
id={clickedFieldId}
|
||||
disabled={disabled}
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
borderRadius: theme.palette?.textFieldStyle.borderRadius,
|
||||
width: "100%",
|
||||
maxHeight: multiline === true ? undefined : 40,
|
||||
minHeight: 40,
|
||||
@@ -3816,7 +3862,7 @@ const ParsedAction = (props) => {
|
||||
<ButtonGroup color="secondary" orientation={multiline ? "vertical" : "horizontal"}>
|
||||
<Tooltip title="Autocomplete text" placement="bottom">
|
||||
<AddCircleOutlineIcon
|
||||
style={{ color: "rgba(255,255,255,0.7)", cursor: "pointer", margin: multiline ? 5 : 0, }}
|
||||
style={{ color: theme.palette.textPrimary, cursor: "pointer", margin: multiline ? 5 : 0, }}
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
|
||||
@@ -4132,15 +4178,15 @@ const ParsedAction = (props) => {
|
||||
datafield = (
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
borderRadius: theme.palette?.textFieldStyle.borderRadius,
|
||||
}}
|
||||
InputProps={{
|
||||
endAdornment: hideExtraTypes ? null : (
|
||||
<InputAdornment position="end">
|
||||
<Tooltip title="Autocomplete text" placement="top">
|
||||
<AddCircleOutlineIcon
|
||||
style={{ cursor: "pointer" }}
|
||||
style={{ cursor: "pointer", color: theme.palette.textPrimary }}
|
||||
onClick={(event) => {
|
||||
setMenuPosition({
|
||||
top: event.pageY + 10,
|
||||
@@ -4199,6 +4245,14 @@ const ParsedAction = (props) => {
|
||||
<Select
|
||||
MenuProps={{
|
||||
disableScrollLock: true,
|
||||
PaperProps: {
|
||||
sx: {
|
||||
'& .MuiList-root': {
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
SelectDisplayProps={{
|
||||
style: {
|
||||
@@ -4237,9 +4291,12 @@ const ParsedAction = (props) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={data}
|
||||
style={{
|
||||
sx={{
|
||||
backgroundColor: selected ? theme.palette.backgroundColor : theme.palette.inputColor,
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor
|
||||
},
|
||||
}}
|
||||
value={data}
|
||||
>
|
||||
@@ -4690,7 +4747,7 @@ const ParsedAction = (props) => {
|
||||
width: 24,
|
||||
height: 24,
|
||||
marginRight: 10,
|
||||
color: "rgba(255,255,255,0.6)",
|
||||
color: theme.palette.textPrimary,
|
||||
}}
|
||||
onClick={() => {
|
||||
setAuthenticationModalOpen(true);
|
||||
@@ -4708,7 +4765,7 @@ const ParsedAction = (props) => {
|
||||
>
|
||||
<PriorityHighIcon
|
||||
style={{
|
||||
color: "rgba(255,255,255,0.5)",
|
||||
color: theme.palette.textPrimary,
|
||||
marginRight: 0,
|
||||
}} />
|
||||
</Tooltip>
|
||||
@@ -4720,7 +4777,7 @@ const ParsedAction = (props) => {
|
||||
placement="top"
|
||||
>
|
||||
<AutoFixHighIcon style={{
|
||||
color: "rgba(255,255,255,0.7)",
|
||||
color: theme.palette.textPrimary,
|
||||
marginRight: 10,
|
||||
}} />
|
||||
</Tooltip>
|
||||
@@ -4747,7 +4804,7 @@ const ParsedAction = (props) => {
|
||||
flex: "10",
|
||||
marginTop: "auto",
|
||||
marginBottom: "auto",
|
||||
color: "#C5C5C5",
|
||||
color: theme.palette.textPrimary,
|
||||
}}
|
||||
>
|
||||
{tmpitem} <span style={{ color: theme.palette.main }}>{selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""}</span>
|
||||
@@ -4776,7 +4833,7 @@ const ParsedAction = (props) => {
|
||||
{((data.options !== undefined && data.options !== null && data.options.length > 0) || (selectedActionParameters[count].options !== undefined && selectedActionParameters[count].options !== null && selectedActionParameters[count].options.length > 0)) ? null :
|
||||
<Tooltip title="Expand editor window" placement="top">
|
||||
<OpenInFullIcon
|
||||
style={{ color: "rgba(255,255,255,0.7)", cursor: "pointer", margin: multiline ? 5 : 0, height: 20, width: 20, }}
|
||||
style={{ color: theme.palette.textPrimary, cursor: "pointer", margin: multiline ? 5 : 0, height: 20, width: 20, }}
|
||||
onMouseOver={(event) => {
|
||||
const clickedField = document.getElementById(clickedFieldId)
|
||||
if (clickedField !== null) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useState, useEffect, useContext, memo } from "react";
|
||||
|
||||
import { toast } from "react-toastify";
|
||||
import theme from "../theme.jsx";
|
||||
import { getTheme } from "../theme.jsx";
|
||||
import { v4 as uuidv4, v5 as uuidv5, validate as isUUID, } from "uuid";
|
||||
import {
|
||||
Paper,
|
||||
@@ -18,6 +17,7 @@ import {
|
||||
TextField,
|
||||
MenuItem,
|
||||
IconButton,
|
||||
Box,
|
||||
} from "@mui/material";
|
||||
|
||||
import {
|
||||
@@ -41,7 +41,8 @@ const useStyles = makeStyles({
|
||||
|
||||
const Priorities = memo((props) => {
|
||||
const { globalUrl, userdata,clickedFromOrgTab,selectedOrganization, handleEditOrg, serverside, billingInfo, stripeKey, checkLogin, setAdminTab, setCurTab, notifications, setNotifications, } = props;
|
||||
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
const [showDismissed, setShowDismissed] = React.useState(false);
|
||||
const [showRead, setShowRead] = React.useState(false);
|
||||
const [appFramework, setAppFramework] = React.useState({});
|
||||
@@ -353,13 +354,13 @@ const Priorities = memo((props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{width: "100%", height: "100%", boxSizing: 'border-box', transition: 'width 0.3s ease', padding: clickedFromOrgTab ? "27px 10px 19px 27px":null, height: clickedFromOrgTab ? "auto":null, minHeight: 843, backgroundColor: clickedFromOrgTab ? '#212121':null, borderRadius: clickedFromOrgTab ? '16px':null, }}>
|
||||
<div style={{ maxHeight: 1700, overflowY: "auto", width: '100%', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{width: "100%", height: "100%", boxSizing: 'border-box', transition: 'width 0.3s ease', padding: clickedFromOrgTab ? "27px 10px 19px 27px":null, height: clickedFromOrgTab ? "auto":null, minHeight: 843, backgroundColor: clickedFromOrgTab ? theme.palette.platformColor :null, borderRadius: clickedFromOrgTab ? '16px':null, }}>
|
||||
<div style={{ maxHeight: 1700, overflowY: "auto", width: '100%', scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<div style={{maxWidth: "calc(100% - 20px)"}}>
|
||||
<Typography variant="h5" style={{ color: "rgba(241, 241, 241, 1)", fontSize: 24, fontWeight: 600, textAlign: "left" }}>
|
||||
<Typography variant="h5" style={{ fontSize: 24, fontWeight: 500, textAlign: "left" }}>
|
||||
Notification Workflow
|
||||
</Typography>
|
||||
<Typography style={{ color: "rgba(158, 158, 158, 1)", fontSize: 16, fontWeight: 400, marginTop: 5, }}>
|
||||
<Typography color="textSecondary" style={{ fontSize: 16, fontWeight: 400, marginTop: 5, }}>
|
||||
The notification workflow triggers when an error occurs in one of your workflows. Each individual one will only start a workflow once every 2 minutes. <b>You can point child org notifications into the parent org notification by choosing it in the list.</b>
|
||||
</Typography>
|
||||
|
||||
@@ -382,8 +383,9 @@ const Priorities = memo((props) => {
|
||||
classes={{ inputRoot: classes.inputRoot }}
|
||||
ListboxProps={{
|
||||
style: {
|
||||
backgroundColor: "#212121",
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: theme.palette.text.primary,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
},
|
||||
}}
|
||||
getOptionLabel={(option) => {
|
||||
@@ -404,8 +406,9 @@ const Priorities = memo((props) => {
|
||||
options={workflows}
|
||||
fullWidth
|
||||
style={{
|
||||
backgroundColor: "#212121",
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
borderRadius: theme.palette.textFieldStyle.borderRadius,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
height: 35,
|
||||
marginBottom: 40,
|
||||
}}
|
||||
@@ -449,8 +452,8 @@ const Priorities = memo((props) => {
|
||||
<MenuItem
|
||||
{...props}
|
||||
style={{
|
||||
// backgroundColor: theme.palette.inputColor,
|
||||
color: data.id === workflow.id ? "red" : "white",
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: data.id === workflow.id ? "red" : theme.palette.text.primary,
|
||||
borderBottom: data.id === "parent" ? "2px solid rgba(255,255,255,0.5)" : null
|
||||
}}
|
||||
value={data}
|
||||
@@ -470,8 +473,9 @@ const Priorities = memo((props) => {
|
||||
<TextField
|
||||
{...params}
|
||||
style={{
|
||||
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||
borderRadius: 4,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
borderRadius: theme.palette.textFieldStyle.borderRadius,
|
||||
height: 35,
|
||||
fontSize: 16,
|
||||
marginTop: "16px"
|
||||
@@ -523,7 +527,8 @@ const Priorities = memo((props) => {
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
borderRadius: 4,
|
||||
height: 35,
|
||||
fontSize: 16,
|
||||
@@ -548,7 +553,7 @@ const Priorities = memo((props) => {
|
||||
|
||||
{notificationWorkflow === undefined || notificationWorkflow === null || notificationWorkflow.length === 0 ? null :
|
||||
<div>
|
||||
<Button variant="outlined" color="secondary" style={{marginTop: 5, textTransform: "none", }} onClick={() => {
|
||||
<Button disableElevation variant="outlined" color="secondary" style={{marginTop: 5, textTransform: "none", }} onClick={() => {
|
||||
if (notificationWorkflow === "parent") {
|
||||
toast.error("Can't send test notifications to the parent org's notification workflow.")
|
||||
return
|
||||
@@ -599,21 +604,21 @@ const Priorities = memo((props) => {
|
||||
</div>
|
||||
}
|
||||
|
||||
<Typography style={{marginTop: 50, fontSize: 24, fontWeight: 'bold', display: clickedFromOrgTab?null:"inline", marginBottom: clickedFromOrgTab? 8:null, color: clickedFromOrgTab?"#ffffff":null }}>Notifications ({
|
||||
<Typography variant="h5" style={{marginTop: 50, fontSize: 24, display: clickedFromOrgTab?null:"inline", marginBottom: clickedFromOrgTab? 8:null, }}>Notifications ({
|
||||
notifications?.filter((notification) => showRead === true || notification.read === false).length
|
||||
})</Typography>
|
||||
|
||||
<span style={{ fontSize: 16, marginLeft: clickedFromOrgTab?null:25, color: clickedFromOrgTab?"#9E9E9E":null, }}>
|
||||
<Typography variant="body2" color="textSecondary" style={{ fontSize: 16, marginLeft: clickedFromOrgTab?null:25, color: clickedFromOrgTab?"#9E9E9E":null, }}>
|
||||
Notifications help you find potential problems with your workflows and apps.
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/organizations#notifications"
|
||||
style={{ textDecoration: clickedFromOrgTab?null:"none", color: clickedFromOrgTab?"#FF8444":"#f85a3e" }}
|
||||
style={{ textDecoration: clickedFromOrgTab?null:"none", color: theme.palette.linkColor }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
<div/>
|
||||
<div style={{display: "flex", marginTop: 10, marginBottom: 10, }}>
|
||||
<Switch
|
||||
@@ -621,7 +626,7 @@ const Priorities = memo((props) => {
|
||||
onChange={() => {
|
||||
setShowRead(!showRead);
|
||||
}}
|
||||
/><span style={{marginTop: 5, }}> Show read </span>
|
||||
/><Typography style={{marginTop: 5, }}> Show read </Typography>
|
||||
{notifications !== undefined && notifications !== null && notifications.length > 1 ? (
|
||||
<Button
|
||||
color="primary"
|
||||
@@ -641,18 +646,18 @@ const Priorities = memo((props) => {
|
||||
|
||||
{clickedFromOrgTab? null : <Divider style={{marginTop: 50, marginBottom: 50, }} />}
|
||||
|
||||
<h2 style={{ display: clickedFromOrgTab ? null:"inline", marginBottom: clickedFromOrgTab ? 8:null, marginTop: clickedFromOrgTab ? 60 : null, color: clickedFromOrgTab ? "#ffffff" : null }}>Suggestions</h2>
|
||||
<span style={{ fontSize: 16, color: clickedFromOrgTab ?"#9E9E9E":null,marginLeft: clickedFromOrgTab ?null:25, }}>
|
||||
<Typography variant="h5" style={{ display: clickedFromOrgTab ? null:"inline", marginBottom: clickedFromOrgTab ? 8:null, marginTop: clickedFromOrgTab ? 60 : null, }}>Suggestions</Typography>
|
||||
<Typography variant="body2" color="texSecondary" style={{ fontSize: 16, 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.
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/organizations#priorities"
|
||||
style={{ textDecoration: clickedFromOrgTab ?null:"none", color: clickedFromOrgTab ?"#FF8444":"#f85a3e" }}
|
||||
style={{ textDecoration: clickedFromOrgTab ?null:"none", color: clickedFromOrgTab ? theme.palette.linkColor :"#f85a3e" }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
<div style={{marginTop: 10, }}/>
|
||||
<Switch
|
||||
checked={showDismissed}
|
||||
@@ -699,7 +704,8 @@ const NotificationItem = memo((props) => {
|
||||
var image = "";
|
||||
var orgName = "";
|
||||
var orgId = "";
|
||||
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
var highlighted = selectedExecutionId === "" && selectedWorkflow === "" ? false : data.reference_url === undefined || data.reference_url === null || data.reference_url.length === 0 ? false : data.reference_url.includes(selectedExecutionId) || data.reference_url.includes(selectedWorkflow)
|
||||
|
||||
@@ -755,16 +761,21 @@ const NotificationItem = memo((props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper
|
||||
<Box
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor.backgroundColor,
|
||||
backgroundColor: theme.palette.cardBackgroundColor,
|
||||
width: clickedFromOrgTab ? null : notificationWidth,
|
||||
padding: 30,
|
||||
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
marginBottom: 20,
|
||||
border: highlighted ? "2px solid #f85a3e" : null,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
}}
|
||||
sx={{
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.cardHoverColor,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div style={{display: "flex", }}>
|
||||
{data.amount === 1 && data.read === false ?
|
||||
@@ -786,8 +797,6 @@ const NotificationItem = memo((props) => {
|
||||
{data.read === false ?
|
||||
<Chip
|
||||
label={"Unread"}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{marginRight: 15, height: 25, }}
|
||||
/>
|
||||
:
|
||||
@@ -814,10 +823,10 @@ const NotificationItem = memo((props) => {
|
||||
<div style={{ display: "flex" }}>
|
||||
<ButtonGroup style={{marginTop: 15, minHeight: 50, maxHeight: 50, }}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
style={{
|
||||
textTransform: "none",
|
||||
border: "1px solid #ff8544",
|
||||
color: "#ff8544",
|
||||
opacity: data.reference_url ? 1 : 0.5,
|
||||
cursor: data.reference_url ? "pointer" : "not-allowed",
|
||||
}}
|
||||
@@ -922,7 +931,7 @@ const NotificationItem = memo((props) => {
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
</Paper>
|
||||
</Box>
|
||||
);
|
||||
})
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { getTheme } from "../theme.jsx";
|
||||
import ReactGA from 'react-ga4';
|
||||
import theme from "../theme.jsx";
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
import { findSpecificApp } from "../components/AppFramework.jsx"
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import {
|
||||
Paper,
|
||||
Typography,
|
||||
@@ -23,7 +23,8 @@ import {
|
||||
|
||||
const Priority = (props) => {
|
||||
const { globalUrl, clickedFromOrgTab,userdata, serverside, priority, checkLogin, setAdminTab, setCurTab, appFramework, } = props;
|
||||
|
||||
const { themeMode, supportEmail } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
const isCloud = (window.location.host === "localhost:3002" || window.location.host === "shuffler.io") ? true : (process.env.IS_SSR === "true");
|
||||
let navigate = useNavigate();
|
||||
|
||||
@@ -113,7 +114,7 @@ const Priority = (props) => {
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
toast("Failed dismissing alert. Please contact support@shuffler.io if this persists.");
|
||||
toast(`Failed dismissing alert. Please contact ${supportEmail} if this persists.`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -121,10 +122,10 @@ const Priority = (props) => {
|
||||
const srcSize = realignedSrc ? 35 : 30
|
||||
const dstSize = realignedDst ? 35 : 30
|
||||
return (
|
||||
<div style={{border: priority.active === false ? "1px solid #000000" : priority.severity === 1 ? "1px solid #f85a3e" : clickedFromOrgTab ?null:"1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette?.borderRadius, marginTop: 10, marginBottom: 10, padding: clickedFromOrgTab ? 24:15, textAlign: "center", minHeight: isCloud ? 70 : 100, maxHeight: isCloud ? 70 : 100, textAlign: "left", backgroundColor: clickedFromOrgTab ? "#1A1A1A": theme.palette.surfaceColor, display: "flex", }}>
|
||||
<div style={{border: priority.active === false ? "1px solid #000000" : priority.severity === 1 ? "1px solid #f85a3e" : clickedFromOrgTab ?null:"1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette?.borderRadius, marginTop: 10, marginBottom: 10, padding: clickedFromOrgTab ? 24:15, textAlign: "center", minHeight: isCloud ? 70 : 100, maxHeight: isCloud ? 70 : 100, textAlign: "left", backgroundColor: clickedFromOrgTab ? theme.palette.backgroundColor : theme.palette.surfaceColor, display: "flex", }}>
|
||||
<div style={{flex: 2, overflow: "hidden",}}>
|
||||
<span style={{display: "flex", }}>
|
||||
{priority.type === "usecase" || priority.type == "apps" ? <AutoFixHighIcon style={{height: 19, width: 19, marginLeft: 3, marginRight: 10, }}/> : null}
|
||||
{priority.type === "usecase" || priority.type == "apps" ? <AutoFixHighIcon style={{height: 19, width: 19, marginLeft: 3, marginRight: 10, color: theme.palette.text.primary}}/> : null}
|
||||
<Typography variant="body1" >
|
||||
{priority.name}
|
||||
</Typography>
|
||||
@@ -138,7 +139,7 @@ const Priority = (props) => {
|
||||
|
||||
{newdescription.split("&").length > 3 ?
|
||||
<span style={{display: "flex", }}>
|
||||
<ArrowForwardIcon style={{marginLeft: 15, marginRight: 15, }}/>
|
||||
<ArrowForwardIcon style={{marginLeft: 15, marginRight: 15, color: theme.palette.text.primary }}/>
|
||||
<img src={newdescription.split("&")[3]} alt={priority.name+"2"} style={{height: dstSize, width: dstSize, marginRight: realignedDst ? -5 : 10, borderRadius: theme.palette?.borderRadius-3, marginTop: realignedDst ? 5 : 0 }} />
|
||||
<Typography variant="body2" color="textSecondary" style={{marginTop: 3}}>
|
||||
{newdescription.split("&")[2]}
|
||||
@@ -154,7 +155,7 @@ const Priority = (props) => {
|
||||
}
|
||||
</div>
|
||||
<div style={{flex: 1, display: "flex", marginLeft: 30, }}>
|
||||
<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={() => {
|
||||
<Button style={{height: 50, borderRadius: 4, fontSize:16, boxShadow: clickedFromOrgTab ? "none":null,textTransform: clickedFromOrgTab ? 'capitalize':null, marginTop: 8, width: 175, marginRight: 10, }} variant="outlined" color="primary" onClick={() => {
|
||||
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
@@ -180,10 +181,9 @@ const Priority = (props) => {
|
||||
Explore
|
||||
</Button>
|
||||
{priority.active === true ?
|
||||
<Button style={{borderRadius: 25, fontSize:16, boxShadow: clickedFromOrgTab ? "none":null,textTransform: clickedFromOrgTab ? 'capitalize':null, width: 100, height: 50, marginTop: 8, }} variant="text" color="secondary" onClick={() => {
|
||||
<Button style={{borderRadius: 4, fontSize:16, boxShadow: clickedFromOrgTab ? "none":null,textTransform: clickedFromOrgTab ? 'capitalize':null, width: 100, height: 50, marginTop: 8, }} variant="outlined" color="secondary" onClick={() => {
|
||||
// dismiss -> get envs
|
||||
changeRecommendation(priority, "dismiss")
|
||||
|
||||
// Check window location if it's /workflows
|
||||
if (window.location.pathname === "/workflows") {
|
||||
// Set local storage to hide priorities for now
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react"
|
||||
import React, {useContext} from "react"
|
||||
|
||||
import { Link } from "react-router-dom";
|
||||
import {
|
||||
@@ -10,14 +10,20 @@ import {
|
||||
} from "@mui/material"
|
||||
import { useNavigate } from "react-router";
|
||||
import theme from "../theme.jsx";
|
||||
|
||||
import { getTheme } from "../theme.jsx";
|
||||
import {
|
||||
Lock as LockIcon,
|
||||
} from '@mui/icons-material';
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
// onclickHandler = function override from parent onclick
|
||||
const RecentWorkflow = ({ workflow, onclickHandler, leftNavOpen, currentWorkflowId, }) => {
|
||||
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [hovered, setHovered] = React.useState(false)
|
||||
@@ -87,7 +93,7 @@ const RecentWorkflow = ({ workflow, onclickHandler, leftNavOpen, currentWorkflow
|
||||
transition: "opacity 0.1s",
|
||||
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
backgroundColor: hovered || currentWorkflowId === workflow.id ? "#1f1f1f" : "transparent",
|
||||
backgroundColor: hovered || currentWorkflowId === workflow.id ? theme.palette.hoverColor : "transparent",
|
||||
}}
|
||||
disableRipple
|
||||
>
|
||||
@@ -127,7 +133,6 @@ const RecentWorkflow = ({ workflow, onclickHandler, leftNavOpen, currentWorkflow
|
||||
))}
|
||||
<Typography
|
||||
style={{
|
||||
color: "#CDCDCD",
|
||||
fontSize: 16,
|
||||
marginLeft: 8,
|
||||
maxWidth: 180,
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import React, { useState, useEffect, useLayoutEffect } from "react";
|
||||
import React, { useState, useEffect, useLayoutEffect, useContext, useMemo } from "react";
|
||||
import * as cytoscape from "cytoscape";
|
||||
import CytoscapeComponent from "react-cytoscapejs";
|
||||
import cystyle from "../defaultCytoscapeStyle.jsx";
|
||||
import defaultCytoscapeStyle from "../defaultCytoscapeStyle.jsx";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import { getTheme } from "../theme.jsx";
|
||||
|
||||
const surfaceColor = "#27292D";
|
||||
const CytoscapeWrapper = (props) => {
|
||||
const { globalUrl, inworkflow, height, width } = props;
|
||||
|
||||
const {themeMode} = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
const cystyle = useMemo(() => defaultCytoscapeStyle(theme), [themeMode]);
|
||||
const [elements, setElements] = useState([]);
|
||||
const [workflow, setWorkflow] = useState(inworkflow);
|
||||
const [cy, setCy] = React.useState();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
|
||||
import {
|
||||
TextField,
|
||||
@@ -17,10 +17,11 @@ import {
|
||||
IconButton,
|
||||
Switch,
|
||||
} from '@mui/material';
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
|
||||
import { toast } from "react-toastify"
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import dayjs from 'dayjs';
|
||||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'
|
||||
import Pagination from '@mui/material/Pagination';
|
||||
@@ -39,7 +40,8 @@ import {
|
||||
EditNote as EditNoteIcon,
|
||||
AccountTree as AccountTreeIcon,
|
||||
Cached as CachedIcon,
|
||||
FilterAltOff as FilterAltOffIcon
|
||||
FilterAltOff as FilterAltOffIcon,
|
||||
Send as SendIcon,
|
||||
} from '@mui/icons-material';
|
||||
|
||||
import { DataGrid, GridColDef, GridValueGetterParams } from '@mui/x-data-grid'
|
||||
@@ -69,6 +71,8 @@ const RuntimeDebugger = (props) => {
|
||||
const [endTime, setEndTime] = useState("")
|
||||
const [startTime, setStartTime] = useState("")
|
||||
const [totalCount, setTotalCount] = useState(0)
|
||||
const {themeMode, supportEmail} = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const [workflow, setWorkflow] = useState({})
|
||||
const [ignoreOrg, setIgnoreOrg] = useState(false)
|
||||
@@ -107,7 +111,7 @@ const RuntimeDebugger = (props) => {
|
||||
|
||||
var maxworkflows = 5
|
||||
|
||||
console.log("Looking for MAX this amount of workflows: ", maxworkflows)
|
||||
//console.log("Looking for MAX this amount of workflows: ", maxworkflows)
|
||||
for (let key in workflows) {
|
||||
if (key > maxworkflows) {
|
||||
break
|
||||
@@ -347,6 +351,9 @@ const RuntimeDebugger = (props) => {
|
||||
source = "rerun of a previous run"
|
||||
} else if (source === "form") {
|
||||
foundSource = <EditNoteIcon style={{color: theme.palette.primary.secondary, height: imageSize, width: imageSize, }} />
|
||||
} else if (source === "single_action" || source == "single_api" || source === "direct_api") {
|
||||
foundSource = <SendIcon color="secondary" style={{height: imageSize-5, }} />
|
||||
source = "Single API call"
|
||||
} else {
|
||||
source = "manual"
|
||||
}
|
||||
@@ -354,12 +361,12 @@ const RuntimeDebugger = (props) => {
|
||||
var imageSource = "";
|
||||
if (params?.row?.org?.id?.length > 0) {
|
||||
if (params?.row?.org?.image?.length > 0){
|
||||
imageSource = params?.row.org?.image
|
||||
imageSource = params?.row?.org?.image
|
||||
}else {
|
||||
imageSource = "/images/no_image.png"
|
||||
}
|
||||
} else {
|
||||
if (userdata?.active_org.image?.length > 0){
|
||||
if (userdata?.active_org?.image?.length > 0){
|
||||
imageSource = userdata?.active_org?.image
|
||||
}else {
|
||||
imageSource = "/images/no_image.png"
|
||||
@@ -629,7 +636,7 @@ const RuntimeDebugger = (props) => {
|
||||
</Link>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip arrow title="Force continue workflow. Only workflows for workflows in EXECUTING state. This is NOT a rerun, but way for Shuffle to figure out the next steps automatically. If the execution doesn't finish even after trying this, please contact support@shuffler.io">
|
||||
<Tooltip arrow title={`Force continue workflow. Only workflows for workflows in EXECUTING state. This is NOT a rerun, but way for Shuffle to figure out the next steps automatically. If the execution doesn't finish even after trying this, please contact ${supportEmail}`}>
|
||||
<IconButton
|
||||
style={{marginLeft: 5, }}
|
||||
disabled={params.row.status !== "EXECUTING"}
|
||||
@@ -812,7 +819,7 @@ const RuntimeDebugger = (props) => {
|
||||
<div style={{display: "flex", paddingTop: 50, }}>
|
||||
<div style={{display: 'flex', flexDirection: 'column'}}>
|
||||
<div style={{display: "flex", width: "100%", }}>
|
||||
<h1 style={{flex: 3, whiteSpace: "nowrap" }}>Workflow Run Debugger {totalCount !== 0 ? ` (~${totalCount})` : ""}</h1>
|
||||
<Typography variant="h3" style={{flex: 3, whiteSpace: "nowrap" }}>Workflow Run Debugger {totalCount !== 0 ? ` (~${totalCount})` : ""}</Typography>
|
||||
{selectedWorkflowExecutions.length > 0 ?
|
||||
<ButtonGroup>
|
||||
<Tooltip title="Reruns ALL selected workflows. This will make a new execution for them, and not continue the existing.">
|
||||
@@ -890,7 +897,8 @@ const RuntimeDebugger = (props) => {
|
||||
fullWidth
|
||||
value={searchQuery}
|
||||
style={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.textColor,
|
||||
marginTop: 20,
|
||||
marginLeft: 10,
|
||||
marginRight: 12,
|
||||
@@ -901,7 +909,8 @@ const RuntimeDebugger = (props) => {
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.textColor,
|
||||
fontSize: "1em",
|
||||
height: 51,
|
||||
width: 693,
|
||||
@@ -951,7 +960,7 @@ const RuntimeDebugger = (props) => {
|
||||
}
|
||||
color="secondary"
|
||||
/>
|
||||
<Typography variant="body2" style={{color: "white", }}>Show workflow runs from suborgs</Typography>
|
||||
<Typography variant="body2">Show workflow runs from suborgs</Typography>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -999,8 +1008,8 @@ const RuntimeDebugger = (props) => {
|
||||
classes={{ inputRoot: classes.inputRoot }}
|
||||
ListboxProps={{
|
||||
style: {
|
||||
backgroundColor: "#1a1a1a",
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.textColor,
|
||||
},
|
||||
}}
|
||||
getOptionLabel={(option) => {
|
||||
@@ -1018,7 +1027,7 @@ const RuntimeDebugger = (props) => {
|
||||
options={workflows}
|
||||
fullWidth
|
||||
style={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
height: 50,
|
||||
borderRadius: 4,
|
||||
marginLeft: 5,
|
||||
@@ -1063,8 +1072,13 @@ const RuntimeDebugger = (props) => {
|
||||
}>
|
||||
<MenuItem
|
||||
style={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
color: data.id === workflow.id ? "red" : "white",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: data.id === workflow.id ? "red" : theme.palette.textColor,
|
||||
}}
|
||||
sx={{
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor,
|
||||
},
|
||||
}}
|
||||
value={data}
|
||||
onClick={(e) => {
|
||||
@@ -1082,9 +1096,16 @@ const RuntimeDebugger = (props) => {
|
||||
return (
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.textColor,
|
||||
borderRadius: 4,
|
||||
}}
|
||||
inputProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.textColor,
|
||||
},
|
||||
}}
|
||||
{...params}
|
||||
label="Workflow"
|
||||
variant="outlined"
|
||||
@@ -1128,9 +1149,7 @@ const RuntimeDebugger = (props) => {
|
||||
|
||||
<Tooltip title="Clear all filters and search parameters">
|
||||
<Button
|
||||
style={{ marginLeft: 10, minHeight: 60, marginTop: 10, backgroundColor: "#1a1a1a", border: "1px solid #424242", boxShadow: 'none', borderRadius: 4, width: 81, height: 51, marginRight: 15 }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{ marginLeft: 10, minHeight: 60, marginTop: 10, backgroundColor: theme.palette.backgroundColor, border: "1px solid #424242", boxShadow: 'none', borderRadius: 4, width: 81, height: 51, marginRight: 15 }}
|
||||
onClick={() => {
|
||||
setWorkflowId("")
|
||||
setWorkflow({"id": "", "name": "All Workflows"})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { forwardRef, memo, useContext, useEffect } from 'react';
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import { toast } from "react-toastify" ;
|
||||
import {
|
||||
Divider,
|
||||
@@ -33,6 +33,9 @@ const SchedulesTab = memo((props) => {
|
||||
const [pipelineModalOpen, setPipelineModalOpen] = React.useState(false);
|
||||
const [newPipelineValue, setNewPipelineValue] = React.useState("export | sigma /tmp/sigma_rules | to SHUFFLE_WEBHOOK");
|
||||
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
useEffect(() => {
|
||||
if (allSchedules.length === 0 && webHooks.length === 0 && pipelines.length === 0) {
|
||||
handleGetAllTriggers()
|
||||
@@ -142,11 +145,11 @@ const SchedulesTab = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<span style={{ color: "white" }}>
|
||||
<Typography variant='h5' color="textPrimary" >
|
||||
Run a Tenzir pipeline
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography variant="body2" color="textSecondary" style={{marginTop: 10, }}>
|
||||
Alpha feature. Deploys to the first available Orborus location. <a href="https://docs.tenzir.com/pipelines" target="_blank" rel="noopener noreferrer" style={{ color: "#ff8544" }}>Explore Tenzir Pipelines</a>. The example below exports everything in the Tenzir database, runs Sigma rules on it, and forwards the results to a Shuffle webhook.
|
||||
Alpha feature. Deploys to the first available Orborus location. <a href="https://docs.tenzir.com/pipelines" target="_blank" rel="noopener noreferrer" style={{ color: theme.palette.primary.main }}>Explore Tenzir Pipelines</a>. The example below exports everything in the Tenzir database, runs Sigma rules on it, and forwards the results to a Shuffle webhook.
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
@@ -173,17 +176,16 @@ const SchedulesTab = memo((props) => {
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", color: "#ff8544" }}
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", color: theme.palette.primary.main }}
|
||||
onClick={() => {
|
||||
setPipelineModalOpen(false)
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", backgroundColor: "#ff8544", color: "#1a1a1a" }}
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", }}
|
||||
onClick={() => {
|
||||
submitPipelineWrapper(newPipelineValue)
|
||||
}}
|
||||
@@ -472,7 +474,7 @@ const SchedulesTab = memo((props) => {
|
||||
height: "100%",
|
||||
transition: 'width 0.3s ease',
|
||||
padding: '27px 10px 27px 27px',
|
||||
backgroundColor: '#212121',
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
borderTopRightRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
borderLeft: '1px solid #494949',
|
||||
@@ -480,36 +482,36 @@ const SchedulesTab = memo((props) => {
|
||||
|
||||
{NewPipelineView}
|
||||
|
||||
<div style={{height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<h2 style={{ marginBottom: 8, marginTop: 0, color: "#FFFFFF" }}>
|
||||
<div style={{height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<Typography variant='h5' color="textPrimary" style={{ marginBottom: 8, marginTop: 0, }}>
|
||||
Triggers
|
||||
</h2>
|
||||
<Typography variant="body1" style={{ marginBottom: 50, marginTop: 0, }} color="textSecondary">
|
||||
</Typography>
|
||||
<Typography variant="body2" style={{ marginBottom: 50, marginTop: 0, }} color="textSecondary">
|
||||
Triggers are Automatic Workflow starters. <b>Status: Schedules ({allSchedules.length}), Webhooks ({webHooks.length}), Pipelines ({pipelines.length})</b>
|
||||
</Typography>
|
||||
|
||||
<div>
|
||||
<h4 style={{ marginBottom: 8, marginTop: 0, color: "#FFFFFF" }}>
|
||||
<Typography variant='h6' color="textPrimary" style={{ marginBottom: 8, marginTop: 0, fontWeight: 500}}>
|
||||
Schedules
|
||||
</h4>
|
||||
<span style={{color:textColor}}>
|
||||
</Typography>
|
||||
<Typography variant='body2' color="textSecondary">
|
||||
Schedules used in Workflows. Makes locating and control easier.{" "}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/organizations#schedules"
|
||||
style={{ color:"#FF8444" }}
|
||||
style={{ color: theme.palette.primary.main }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
<div style={{height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{height: "100%", width: "calc(100% - 20px)", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<div
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.defaultBorder,
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
@@ -525,7 +527,7 @@ const SchedulesTab = memo((props) => {
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0
|
||||
}}>
|
||||
<ListItem style={{width: "100%", paddingTop: 10, paddingBottom: 10, paddingRight: 10, borderBottom: "1px solid #494949", display: 'table-row'}}>
|
||||
<ListItem style={{width: "100%", paddingTop: 10, paddingBottom: 10, paddingRight: 10, borderBottom: theme.palette.defaultBorder, display: 'table-row'}}>
|
||||
{["Name", "Interval", "Environment", "Workflow", "Argument", "Action"].map((header, index) => (
|
||||
<ListItemText
|
||||
key={index}
|
||||
@@ -535,7 +537,7 @@ const SchedulesTab = memo((props) => {
|
||||
padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
@@ -546,7 +548,7 @@ const SchedulesTab = memo((props) => {
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "table-row",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
}}
|
||||
>
|
||||
{Array(6)
|
||||
@@ -563,7 +565,7 @@ const SchedulesTab = memo((props) => {
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
height: "20px",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
@@ -575,13 +577,13 @@ const SchedulesTab = memo((props) => {
|
||||
):(
|
||||
allSchedules?.length === 0 ? (
|
||||
<div style={{ textAlign: 'center'}}>
|
||||
<Typography style={{color: "#FFFFFF", fontSize: 16, padding: 20, textAlign: 'center'}}>No schedules found</Typography>
|
||||
<Typography style={{color: theme.palette.text.primary, fontSize: 16, padding: 20, textAlign: 'center'}}>No schedules found</Typography>
|
||||
</div>
|
||||
):(
|
||||
allSchedules.map((schedule, index) => {
|
||||
var bgColor = "#212121"
|
||||
var bgColor = themeMode === "dark" ? "#212121" : "#FFFFFF";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = "#1a1a1a";
|
||||
bgColor = themeMode === "dark" ? "#1A1A1A" : "#EAEAEA";
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -645,7 +647,7 @@ const SchedulesTab = memo((props) => {
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
textDecoration: "none",
|
||||
color: "#f85a3e",
|
||||
color: theme.palette.primary.main,
|
||||
}}
|
||||
href={`/workflows/${schedule.workflow_id}`}
|
||||
target="_blank"
|
||||
@@ -658,7 +660,7 @@ const SchedulesTab = memo((props) => {
|
||||
style={{
|
||||
color:
|
||||
schedule.workflow_id !== "global"
|
||||
? "#FF8444"
|
||||
? theme.palette.primary.main
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
@@ -698,8 +700,7 @@ const SchedulesTab = memo((props) => {
|
||||
style={{
|
||||
textTransform: 'none',
|
||||
fontSize: 16,
|
||||
color: schedule.status === "running" ? '#1a1a1a' : null,
|
||||
backgroundColor: schedule.status === "running" ? '#ff8544' : null,
|
||||
width: 150,
|
||||
}}
|
||||
color={schedule.status === "running" ? "secondary" : "primary"}
|
||||
variant={schedule.status === "running" ? "contained" : "outlined"}
|
||||
@@ -725,23 +726,23 @@ const SchedulesTab = memo((props) => {
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: 50, marginBottom: 20 }}>
|
||||
<h4 style={{color: "#FFFFFF"}} >Webhooks</h4>
|
||||
<span> Webhooks used in Shuffle workflows.
|
||||
<Typography variant='h6' color="textPrimary">Webhooks</Typography>
|
||||
<Typography variant='body2' color="textSecondary"> Webhooks used in Shuffle workflows.
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/triggers#webhooks"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
style={{ color: theme.palette.primary.main }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.defaultBorder,
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
@@ -757,7 +758,7 @@ const SchedulesTab = memo((props) => {
|
||||
paddingBottom: 0,
|
||||
minWidth: 600,
|
||||
}}>
|
||||
<ListItem style={{width:"100%", borderBottom:"1px solid #494949", display: "table-row"}}>
|
||||
<ListItem style={{width:"100%", borderBottom:theme.palette.defaultBorder, display: "table-row"}}>
|
||||
{["Name", "Environment", "Workflow", "URL", "Action"].map((header, index) => (
|
||||
<ListItemText
|
||||
key={index}
|
||||
@@ -767,7 +768,7 @@ const SchedulesTab = memo((props) => {
|
||||
padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
position: "sticky",
|
||||
}}
|
||||
/>
|
||||
@@ -779,7 +780,7 @@ const SchedulesTab = memo((props) => {
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "table-row",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
}}
|
||||
>
|
||||
{Array(5)
|
||||
@@ -796,7 +797,7 @@ const SchedulesTab = memo((props) => {
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
height: "20px",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
@@ -808,13 +809,13 @@ const SchedulesTab = memo((props) => {
|
||||
):(
|
||||
webHooks?.length === 0 ? (
|
||||
<div style={{textAlign: "center"}}>
|
||||
<Typography style={{color: "#FFFFFF", padding: 20, fontSize: 16, textAlign: 'center'}}>No webhooks found</Typography>
|
||||
<Typography style={{color: theme.palette.text.primary, padding: 20, fontSize: 16, textAlign: 'center'}}>No webhooks found</Typography>
|
||||
</div>
|
||||
):(
|
||||
webHooks.map((webhook, index) => {
|
||||
var bgColor = "#212121"
|
||||
var bgColor = themeMode === "dark" ? "#212121" : "#FFFFFF";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = "#1a1a1a";
|
||||
bgColor = themeMode === "dark" ? "#1A1A1A" : "#EAEAEA";
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -840,7 +841,7 @@ const SchedulesTab = memo((props) => {
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
textDecoration: "none",
|
||||
color: "#f85a3e",
|
||||
color: theme.palette.primary.main,
|
||||
}}
|
||||
href={`/workflows/${webhook.workflows[0]}`}
|
||||
target="_blank"
|
||||
@@ -853,7 +854,7 @@ const SchedulesTab = memo((props) => {
|
||||
style={{
|
||||
color:
|
||||
webhook.workflows[0].workflow_id !== "global"
|
||||
? "#FF8444"
|
||||
? theme.palette.primary.main
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
@@ -904,6 +905,7 @@ const SchedulesTab = memo((props) => {
|
||||
fontSize: 16,
|
||||
color:webhook.status === "running" ? '#1a1a1a' : null,
|
||||
backgroundColor: webhook.status === "running" ? '#ff8544' : null,
|
||||
width: 150,
|
||||
}}
|
||||
color={webhook.status === "running" ? "secondary" : "primary"}
|
||||
variant={webhook.status === "running" ? "contained" : "outlined"}
|
||||
@@ -928,24 +930,24 @@ const SchedulesTab = memo((props) => {
|
||||
</List>
|
||||
</div>
|
||||
<div style={{ marginTop: 50, marginBottom: 20 }}>
|
||||
<h4 style={{color: "#FFFFFF"}}>Pipelines</h4>
|
||||
<Typography variant='h6' color="textPrimary" >Pipelines</Typography>
|
||||
|
||||
<span>
|
||||
<Typography variant='body2' color="textSecondary" >
|
||||
Controls Pipelines on your Orborus Runners, e.g. for Log Ingestion, MQ subscriptions or Sigma Detections.{" "}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/triggers#pipelines"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
style={{ color: theme.palette.primary.main }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
|
||||
<div style={{marginBottom: 10, marginTop: 10, }}/>
|
||||
|
||||
<Button
|
||||
style={{ backgroundColor: '#ff8544', color: "#1a1a1a", borderRadius: 4, textTransform: "capitalize", fontSize: 16, }}
|
||||
style={{ borderRadius: 4, textTransform: "capitalize", fontSize: 16, }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => setPipelineModalOpen(true)}
|
||||
@@ -958,7 +960,7 @@ const SchedulesTab = memo((props) => {
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.defaultBorder,
|
||||
width: "100%",
|
||||
overflowX: pipelines?.length === 0 ? "hidden" : "auto",
|
||||
paddingBottom: 0,
|
||||
@@ -974,7 +976,7 @@ const SchedulesTab = memo((props) => {
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0
|
||||
}}>
|
||||
<ListItem style={{width:"100%", borderBottom:"1px solid #494949", display: "table-row"}}>
|
||||
<ListItem style={{width:"100%", borderBottom:theme.palette.defaultBorder, display: "table-row"}}>
|
||||
{["Command", "Environment", "Total Runs", "Actions"].map((header, index) => (
|
||||
<ListItemText
|
||||
key={index}
|
||||
@@ -984,7 +986,7 @@ const SchedulesTab = memo((props) => {
|
||||
padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
position: "sticky",
|
||||
}}
|
||||
/>
|
||||
@@ -997,7 +999,7 @@ const SchedulesTab = memo((props) => {
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "table-row",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
}}
|
||||
>
|
||||
{Array(5)
|
||||
@@ -1015,7 +1017,7 @@ const SchedulesTab = memo((props) => {
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
height: "20px",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
@@ -1031,14 +1033,14 @@ const SchedulesTab = memo((props) => {
|
||||
): (
|
||||
pipelines?.length === 0 ? (
|
||||
<div style={{width: "100%", textAlign: "center", }}>
|
||||
<Typography style={{color: "#FFFFFF", padding: 20,width: "100%", fontSize: 16, textAlign: 'center'}}>No pipeline trigger found</Typography>
|
||||
<Typography style={{color: theme.palette.text.primary, padding: 20,width: "100%", fontSize: 16, textAlign: 'center'}}>No pipeline trigger found</Typography>
|
||||
</div>
|
||||
|
||||
):(
|
||||
pipelines.map((pipeline, index) => {
|
||||
var bgColor = "#212121"
|
||||
var bgColor = themeMode === "dark" ? "#212121" : "#FFFFFF";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = "#1a1a1a";
|
||||
bgColor = themeMode === "dark" ? "#1A1A1A" : "#EAEAEA";
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -1094,4 +1096,3 @@ const SchedulesTab = memo((props) => {
|
||||
});
|
||||
|
||||
export default SchedulesTab;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect, useRef, useContext } from 'react';
|
||||
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import { useNavigate, Link, useParams } from "react-router-dom";
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
@@ -58,6 +58,8 @@ const SearchData = props => {
|
||||
const [oldPath, setOldPath] = useState("")
|
||||
const [value, setValue] = useState("");
|
||||
const isDocSearchModal = isDocSearchModalOpen;
|
||||
const {themeMode, supportEmail} = useContext(Context);
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const handleLinkClick = () => {
|
||||
if (searchBarModalOpen) {
|
||||
@@ -140,14 +142,13 @@ const SearchData = props => {
|
||||
>
|
||||
<TextField
|
||||
fullWidth
|
||||
style={{ zIndex: 1100, marginTop: -20, marginBottom: 200, position: "fixed", backgroundColor: theme.palette.inputColor, borderRadius: borderRadius, width: 690, }}
|
||||
style={{ zIndex: 1100, marginTop: -20, marginBottom: 200, position: "fixed", backgroundColor: theme.palette.textFieldStyle.backgroundColor, borderRadius: borderRadius, width: 690, }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: "1em",
|
||||
height: 50,
|
||||
margin: 0,
|
||||
fontSize: "0.9em",
|
||||
paddingLeft: 10,
|
||||
},
|
||||
disableUnderline: true,
|
||||
@@ -217,12 +218,12 @@ const SearchData = props => {
|
||||
const baseImage = <CodeIcon />
|
||||
|
||||
return (
|
||||
<Card elevation={0} style={{ marginRight: 10, marginTop: 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 75, boxShadows: "none", }}>
|
||||
<Card elevation={0} style={{ marginRight: 10, marginTop: 50, color: theme.palette.text.primary, zIndex: 1002, backgroundColor: theme.palette.textFieldStyle.backgroundColor, width: "100%", left: 75, boxShadows: "none", }}>
|
||||
<Typography variant="h6" style={{ margin: "10px 10px 0px 20px", color: "#FF8444", borderBottom: "1px solid", width: 105 }}>
|
||||
Workflows
|
||||
</Typography>
|
||||
|
||||
<List style={{ backgroundColor: theme.palette.inputColor, }}>
|
||||
<List style={{ backgroundColor: themeMode === "dark" ? "#2A2A2A" : "#F5F5F5", }}>
|
||||
{hits.length === 0 ?
|
||||
<ListItem style={outerlistitemStyle}>
|
||||
<ListItemAvatar onClick={() => console.log(hits)}>
|
||||
@@ -242,7 +243,7 @@ const SearchData = props => {
|
||||
overflowX: "hidden",
|
||||
overflowY: "hidden",
|
||||
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
||||
backgroundColor: mouseHoverIndex === index ? "#1f2023" : "inherit",
|
||||
backgroundColor: mouseHoverIndex === index ? theme.palette.hoverColor : "inherit",
|
||||
cursor: "pointer",
|
||||
marginLeft: 5,
|
||||
marginRight: 5,
|
||||
@@ -396,14 +397,14 @@ const SearchData = props => {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
toast(`Failed to ${type} the app for your organization. Please try again or contact support@shuffler.io`)
|
||||
toast(`Failed to ${type} the app for your organization. Please try again or contact ${supportEmail}`)
|
||||
}
|
||||
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success === false) {
|
||||
toast(`Failed to ${type} the app for your organization. Please try again or contact support@shuffler.io for more info`)
|
||||
toast(`Failed to ${type} the app for your organization. Please try again or contact ${supportEmail} for more info`)
|
||||
} else {
|
||||
toast(`App successfully ${type}d. It may now be used in your workflows.`)
|
||||
}
|
||||
@@ -438,7 +439,7 @@ const SearchData = props => {
|
||||
const baseImage = <LibraryBooksIcon />
|
||||
|
||||
return (
|
||||
<Card elevation={0} style={{ marginRight: 10, color: "white", zIndex: 999, backgroundColor: theme.palette.inputColor, width: 685, boxShadows: "none", }}>
|
||||
<Card elevation={0} style={{ marginRight: 10, color: "white", zIndex: 999, backgroundColor: theme.palette.textFieldStyle.backgroundColor, width: 685, boxShadows: "none", }}>
|
||||
{/* <IconButton style={{ zIndex: 5000, position: "absolute", right: 14, color: "grey" }} onClick={() => {
|
||||
setSearchOpen(false)
|
||||
}}>
|
||||
@@ -448,7 +449,7 @@ const SearchData = props => {
|
||||
Apps
|
||||
</Typography>
|
||||
|
||||
<List style={{ backgroundColor: theme.palette.inputColor, }}>
|
||||
<List style={{ backgroundColor: themeMode === "dark" ? "#2A2A2A" : "#F5F5F5", }}>
|
||||
{hits.length === 0 ?
|
||||
<ListItem style={outerlistitemStyle}>
|
||||
<ListItemAvatar onClick={() => console.log(hits)}>
|
||||
@@ -468,7 +469,7 @@ const SearchData = props => {
|
||||
overflowX: "hidden",
|
||||
overflowY: "hidden",
|
||||
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
||||
backgroundColor: mouseHoverIndex === index ? "#1f2023" : "inherit",
|
||||
backgroundColor: mouseHoverIndex === index ? theme.palette.hoverColor : "inherit",
|
||||
cursor: "pointer",
|
||||
marginLeft: 5,
|
||||
marginRight: 5,
|
||||
@@ -630,7 +631,7 @@ const SearchData = props => {
|
||||
//console.log(type, hits.length, hits)
|
||||
|
||||
return (
|
||||
<Card elevation={0} style={{ marginRight: 10, marginTop: isDocSearchModal ? 0 : 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 470, boxShadows: "none", }}>
|
||||
<Card elevation={0} style={{ marginRight: 10, marginTop: isDocSearchModal ? 0 : 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.textFieldStyle.backgroundColor, width: "100%", left: 470, boxShadows: "none", }}>
|
||||
{/* <IconButton style={{ zIndex: 5000, position: "absolute", right: 14, color: "grey" }} onClick={() => {
|
||||
setSearchOpen(false)
|
||||
}}>
|
||||
@@ -650,7 +651,7 @@ const SearchData = props => {
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
*/}
|
||||
<List style={{ backgroundColor: theme.palette.inputColor, marginTop: isDocSearchModal ? 35 : 0, }}>
|
||||
<List style={{ backgroundColor: themeMode === "dark" ? "#2A2A2A" : "#F5F5F5", marginTop: isDocSearchModal ? 35 : 0, }}>
|
||||
{hits.length === 0 ?
|
||||
<ListItem style={outerlistitemStyle}>
|
||||
<ListItemAvatar onClick={() => console.log(hits)}>
|
||||
@@ -670,7 +671,7 @@ const SearchData = props => {
|
||||
overflowX: "hidden",
|
||||
overflowY: "hidden",
|
||||
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
||||
backgroundColor: mouseHoverIndex === index ? "#1f2023" : "inherit",
|
||||
backgroundColor: mouseHoverIndex === index ? theme.palette.hoverColor : "inherit",
|
||||
cursor: "pointer",
|
||||
marginLeft: 5,
|
||||
marginRight: 5,
|
||||
@@ -787,13 +788,20 @@ const SearchData = props => {
|
||||
window.open(modifiedUrl, '_blank');
|
||||
};
|
||||
return (
|
||||
<Card elevation={0} style={{ marginRight: 10, marginTop: 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 470, boxShadows: "none", }}>
|
||||
<Card elevation={0} style={{ marginRight: 10, marginTop: 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.textFieldStyle.backgroundColor, width: "100%", left: 470, boxShadows: "none", }}>
|
||||
<Typography variant="h6" style={{ margin: "10px 10px 0px 20px", color: "#FF8444", borderBottom: "1px solid", width: 152 }}>
|
||||
Discord Chat
|
||||
</Typography>
|
||||
<List style={{ backgroundColor: theme.palette.inputColor, }}>
|
||||
<List style={{ backgroundColor: themeMode === "dark" ? "#2A2A2A" : "#F5F5F5", }}>
|
||||
{hits.length === 0 ?
|
||||
<ListItem style={outerlistitemStyle}>
|
||||
<ListItem
|
||||
sx={{
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor
|
||||
}
|
||||
}}
|
||||
style={outerlistitemStyle}
|
||||
>
|
||||
<ListItemAvatar onClick={() => console.log(hits)}>
|
||||
<Avatar>
|
||||
<FolderIcon />
|
||||
@@ -805,7 +813,11 @@ const SearchData = props => {
|
||||
/>
|
||||
</ListItem>:
|
||||
hits.map((chat, index) => (
|
||||
<ListItem onClick={() => handleHitClick(chat.url)} key={index} style={{ cursor: "pointer", borderBottom: "1px solid rgba(255,255,255,0.4)" }} onMouseOver={() => setMouseHoverIndex(index)}>
|
||||
<ListItem sx={{
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor
|
||||
}
|
||||
}} onClick={() => handleHitClick(chat.url)} key={index} style={{ cursor: "pointer", borderBottom: "1px solid rgba(255,255,255,0.4)" }} onMouseOver={() => setMouseHoverIndex(index)}>
|
||||
<ListItemAvatar>
|
||||
<Avatar src="/discord-logo.png" />
|
||||
</ListItemAvatar>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect, useRef, useContext } from 'react';
|
||||
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import { useNavigate, Link, useParams } from "react-router-dom";
|
||||
import SearchBox from "../components/SearchData.jsx";
|
||||
|
||||
@@ -46,7 +46,8 @@ const chipStyle = {
|
||||
|
||||
const SearchField = props => {
|
||||
const { serverside, userdata, isMobile, isLoaded, globalUrl, isHeader, isLoggedIn, small, rounded } = props
|
||||
|
||||
const {themeMode} = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
const {searchBarModalOpen, setSearchBarModalOpen} = useContext(Context);
|
||||
|
||||
let navigate = useNavigate();
|
||||
@@ -87,7 +88,7 @@ const SearchField = props => {
|
||||
height: 785,
|
||||
borderRadius: 16,
|
||||
border: "1px solid var(--Container-Stroke, #494949)",
|
||||
background: "var(--Container, #000000)",
|
||||
background: theme.palette.DialogStyle.backgroundColor,
|
||||
boxShadow: "0px 16px 24px 8px rgba(0, 0, 0, 0.25)",
|
||||
zIndex: 13000,
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useRef, useState, useEffect, useLayoutEffect, } from 'react';
|
||||
import React, { useRef, useState, useEffect, useLayoutEffect, useContext } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import '../codeeditor-index.css';
|
||||
import {
|
||||
@@ -17,8 +17,8 @@ import {
|
||||
ButtonGroup,
|
||||
Collapse,
|
||||
} from '@mui/material';
|
||||
|
||||
import theme from '../theme.jsx';
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import Checkbox from '@mui/material/Checkbox';
|
||||
import { isMobile } from "react-device-detect"
|
||||
import { NestedMenuItem } from "mui-nested-menu"
|
||||
@@ -149,6 +149,8 @@ const CodeEditor = (props) => {
|
||||
// value: localcodedata,
|
||||
//})
|
||||
// const {codelang, setcodelang} = props
|
||||
const {themeMode, supportEmail} = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const [validation, setValidation] = React.useState(false);
|
||||
const [expOutput, setExpOutput] = React.useState(" ");
|
||||
@@ -1396,7 +1398,7 @@ const CodeEditor = (props) => {
|
||||
|
||||
const usedposition = e.offsetY
|
||||
if (usedposition === undefined || usedposition === null) {
|
||||
toast.info("Error: LayerY is undefined or null. Please contact support@shuffler.io")
|
||||
toast.info(`Error: LayerY is undefined or null. Please contact ${supportEmail}`)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1523,17 +1525,17 @@ const CodeEditor = (props) => {
|
||||
setActiveDialog("codeeditor")
|
||||
}
|
||||
},
|
||||
style: {
|
||||
sx: {
|
||||
// zIndex: 12501,
|
||||
pointerEvents: "auto",
|
||||
color: "white",
|
||||
minWidth: isMobile ? "100%" : isFileEditor ? 650 : "80%",
|
||||
maxWidth: isMobile ? "100%" : isFileEditor ? 650 : 1100,
|
||||
color: theme.palette.DialogStyle.color,
|
||||
minWidth: isMobile ? "100%" : isFileEditor ? "650px" : "80%",
|
||||
maxWidth: isMobile ? "100%" : isFileEditor ? "650px" : "1100px",
|
||||
minHeight: isMobile ? "100%" : "auto",
|
||||
maxHeight: isMobile ? "100%" : 700,
|
||||
maxHeight: isMobile ? "100%" : "700px",
|
||||
border: "3px solid rgba(255,255,255,0.3)",
|
||||
padding: isMobile ? "25px 10px 25px 10px" : 25,
|
||||
backgroundColor: "black",
|
||||
padding: isMobile ? "25px 10px 25px 10px" : "25px",
|
||||
backgroundColor: themeMode === "dark" ? "black" : theme.palette.DialogStyle.backgroundColor,
|
||||
},
|
||||
}}
|
||||
>
|
||||
@@ -1584,7 +1586,10 @@ const CodeEditor = (props) => {
|
||||
color: "grey",
|
||||
}}
|
||||
onClick={() => {
|
||||
if (isFileEditor !== true) {
|
||||
navigate("")
|
||||
}
|
||||
|
||||
setExpansionModalOpen(false)
|
||||
}}
|
||||
>
|
||||
@@ -1728,6 +1733,7 @@ const CodeEditor = (props) => {
|
||||
style={{
|
||||
textTransform: "none",
|
||||
width: 175,
|
||||
textWrap: 'nowrap'
|
||||
}}
|
||||
onClick={(event) => {
|
||||
setSourceDataOpen(!sourceDataOpen)
|
||||
@@ -1747,6 +1753,7 @@ const CodeEditor = (props) => {
|
||||
style={{
|
||||
textTransform: "none",
|
||||
width: 120,
|
||||
textWrap: "nowrap"
|
||||
}}
|
||||
onClick={(event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
@@ -1783,6 +1790,7 @@ const CodeEditor = (props) => {
|
||||
style={{
|
||||
textTransform: "none",
|
||||
width: 145,
|
||||
textWrap: "nowrap"
|
||||
}}
|
||||
onClick={(event) => {
|
||||
setAnchorEl3(event.currentTarget);
|
||||
@@ -1800,6 +1808,7 @@ const CodeEditor = (props) => {
|
||||
style={{
|
||||
textTransform: "none",
|
||||
width: 130,
|
||||
textWrap: "nowrap",
|
||||
}}
|
||||
onClick={(event) => {
|
||||
setMenuPosition({
|
||||
@@ -2266,7 +2275,9 @@ const CodeEditor = (props) => {
|
||||
paddingLeft: 10,
|
||||
paddingTop: 0,
|
||||
display: "flex",
|
||||
cursor: "move"
|
||||
cursor: "move",
|
||||
color: theme.palette.DialogStyle.color,
|
||||
backgroundColor: "transparent",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
@@ -2294,7 +2305,7 @@ const CodeEditor = (props) => {
|
||||
{
|
||||
selectedEdge && Object.keys(selectedEdge).length > 0 ?
|
||||
<ArrowForwardIcon style={{
|
||||
color: "rgba(255,255,255,0.7)",
|
||||
color: theme.palette.textPrimary,
|
||||
fontSize: 18,
|
||||
marginLeft: -5,
|
||||
marginRight: -5,
|
||||
@@ -2319,7 +2330,7 @@ const CodeEditor = (props) => {
|
||||
}
|
||||
</div>
|
||||
:
|
||||
<span style={{ color: "white" }}>
|
||||
<span style={{ color: theme.palette.text.primary }}>
|
||||
{selectedAction.name === "execute_python" || selectedAction.name === "execute_bash" ?
|
||||
"Code to run" :
|
||||
triggerId ?
|
||||
@@ -2337,9 +2348,7 @@ const CodeEditor = (props) => {
|
||||
<Tooltip title="Try it! This runs the Shuffle Tools 'repeat back to me' or 'execute python' action with what you see in the expected output window. Commonly used to test your Python scripts or Liquid filters, not requiring the full workflow to run again." placement="top">
|
||||
<Button
|
||||
id="try-it-button"
|
||||
variant="outlined"
|
||||
disabled={executing}
|
||||
color="primary"
|
||||
style={{
|
||||
border: `1px solid rgba(255, 255, 255, 0.15)`,
|
||||
position: "absolute",
|
||||
@@ -2351,11 +2360,12 @@ const CodeEditor = (props) => {
|
||||
fontWeight: 500,
|
||||
fontSize: 14,
|
||||
textTransform: "none",
|
||||
backgroundColor: "rgba(33, 33, 33, 0.95)",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
backdropFilter: "blur(8px)",
|
||||
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08)",
|
||||
transition: "all 0.2s ease",
|
||||
paddingRight: 20,
|
||||
color: "#FF8544",
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(45, 45, 45, 0.95)",
|
||||
@@ -2376,7 +2386,7 @@ const CodeEditor = (props) => {
|
||||
<span>
|
||||
|
||||
<PlayArrowIcon style={{ height: 18, width: 18, marginBottom: -4, marginLeft: 5, }} />
|
||||
{selectedAction === undefined ? "Try it" : selectedAction.name === "execute_python" ? "Run Python Code" : selectedAction.name === "execute_bash" ? "Run Bash" : "Try it"}
|
||||
{selectedAction === undefined ? <Typography style={{color: "inherit"}}>Try it</Typography> : selectedAction.name === "execute_python" ? "Run Python Code" : selectedAction.name === "execute_bash" ? "Run Bash" : "Try it"}
|
||||
<span
|
||||
style={{
|
||||
color: "#C8C8C8",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { memo, useContext, useEffect, useState } from 'react';
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
import {
|
||||
FormControl,
|
||||
Card,
|
||||
@@ -63,6 +64,8 @@ const TenantsTab = memo((props) => {
|
||||
const [suborglistOpen, setSuborglistOpen] = React.useState(false);
|
||||
const [allTenantsOpen, setAllTenantsOpen] = React.useState(false);
|
||||
const itemColor = "black";
|
||||
const { themeMode, supportEmail, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
useEffect(() => {
|
||||
if(parentOrg !== null && parentOrgFlag === null) {
|
||||
@@ -84,6 +87,9 @@ const TenantsTab = memo((props) => {
|
||||
} else if (regiontag === "ca") {
|
||||
regiontag = "CA";
|
||||
regionCode = "ca";
|
||||
}else if (regiontag === "au") {
|
||||
regiontag = "AUS";
|
||||
regionCode = "au"
|
||||
}
|
||||
}
|
||||
setParentOrgFlag(regionCode);
|
||||
@@ -168,6 +174,9 @@ const TenantsTab = memo((props) => {
|
||||
} else if (regiontag === "ca") {
|
||||
regiontag = "CA";
|
||||
regionCode = "ca";
|
||||
}else if (regiontag === "au") {
|
||||
regiontag = "AUS";
|
||||
regionCode = "au"
|
||||
}
|
||||
}
|
||||
setParentOrgFlag(regionCode);
|
||||
@@ -613,7 +622,7 @@ const TenantsTab = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<span style={{ color: "white" }}>Add Sub-Organization</span>
|
||||
<Typography variant='h5' color="textPrimary">Add Sub-Organization</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<div>
|
||||
@@ -625,7 +634,7 @@ const TenantsTab = memo((props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
@@ -644,15 +653,14 @@ const TenantsTab = memo((props) => {
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", color: "#ff8544" }}
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", color: theme.palette.primary.main }}
|
||||
onClick={() => setModalOpen(false)}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none", backgroundColor: "#ff8544", color: "#1a1a1a"}}
|
||||
style={{ borderRadius: "2px", fontSize: 16, textTransform: "none",}}
|
||||
onClick={() => {
|
||||
createSubOrg(selectedOrganization.id, orgName);
|
||||
}}
|
||||
@@ -739,7 +747,7 @@ const TenantsTab = memo((props) => {
|
||||
}
|
||||
style={{ marginLeft: 15, height: 50, borderRadius: "2px", color: "#1a1a1a", backgroundColor: (!selectedOrganization.cloud_sync &&
|
||||
cloudSyncApikey.length === 0) ||
|
||||
loading ? "rgba(200, 200, 200, 0.5)" : "#ff8544", fontSize: 16, textTransform: "none" }}
|
||||
loading ? "rgba(200, 200, 200, 0.5)" : theme.palette.primary.main, fontSize: 16, textTransform: "none" }}
|
||||
onClick={() => {
|
||||
setLoading(true);
|
||||
enableCloudSync(
|
||||
@@ -784,31 +792,31 @@ const TenantsTab = memo((props) => {
|
||||
const textColor = "#9E9E9E !important";
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121',borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949",}}>
|
||||
<div style={{ width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: theme.palette.platformColor, borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: theme.palette.defaultBorder,}}>
|
||||
{modalView}
|
||||
{cloudSyncModal}
|
||||
<div style={{height: "100%", maxHeight: 1700, overflowY: "auto",overflowX: 'hidden', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
||||
<div style={{height: "100%", maxHeight: 1700, overflowY: "auto",overflowX: 'hidden', scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin' }}>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<h2 style={{ marginBottom: 8, marginTop: 0, color: "#ffffff" }}>Tenants</h2>
|
||||
<span style={{ color: textColor }}>
|
||||
<Typography variant='h5' color="textPrimary" style={{ marginBottom: 8, marginTop: 0 }}>Tenants</Typography>
|
||||
<Typography variant='body2' color="textSecondary">
|
||||
Create, manage and change to sub-organizations (tenants)! {" "}
|
||||
{isCloud
|
||||
? "You can only make a sub organization if you are a customer of shuffle or running a POC of the platform. Please contact support@shuffler.io to try it out."
|
||||
? `You can only make a sub organization if you are a customer of shuffle or running a POC of the platform. Please contact ${supportEmail} to try it out.`
|
||||
: ''}
|
||||
<a
|
||||
href="/docs/organizations"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{ color: "#FF8444" }}
|
||||
style={{ color: theme.palette.linkColor }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
style={{ backgroundColor: '#ff8544', textTransform: 'none', fontSize: 16, color: "#1a1a1a", borderRadius: 4, width: 212, height: 40 }}
|
||||
style={{ textTransform: 'none', fontSize: 16, borderRadius: 4, width: 212, height: 40 }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={userdata.admin !== 'true'}
|
||||
@@ -835,17 +843,15 @@ const TenantsTab = memo((props) => {
|
||||
marginTop: 20,
|
||||
}}
|
||||
>
|
||||
<h3
|
||||
<Typography
|
||||
variant='h6'
|
||||
color="textPrimary"
|
||||
style={{
|
||||
margin: 0,
|
||||
fontSize: '1.2rem',
|
||||
fontWeight: 'bold',
|
||||
letterSpacing: '1px',
|
||||
color: "#ffffff"
|
||||
}}
|
||||
>
|
||||
Your Parent Organization
|
||||
</h3>
|
||||
</Typography>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -859,7 +865,7 @@ const TenantsTab = memo((props) => {
|
||||
/> */}
|
||||
|
||||
|
||||
<div style={{ borderRadius: 4, marginTop: 24, border: "1px solid #494949", width: "100%", overflowX: "auto", paddingBottom: 0 }}>
|
||||
<div style={{ borderRadius: 4, marginTop: 24, border: theme.palette.defaultBorder, width: "100%", overflowX: "auto", paddingBottom: 0 }}>
|
||||
<List
|
||||
style={{
|
||||
width: "100%",
|
||||
@@ -890,7 +896,7 @@ const TenantsTab = memo((props) => {
|
||||
display: "table-cell",
|
||||
padding: "0px 8px 8px 8px",
|
||||
textAlign: "center",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -903,7 +909,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
textAlign: "center",
|
||||
}}
|
||||
@@ -915,7 +921,7 @@ const TenantsTab = memo((props) => {
|
||||
minWidth: 100,
|
||||
maxWidth: 100,
|
||||
display: "table-cell",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
padding: "0px 8px 8px 8px",
|
||||
}}
|
||||
/>
|
||||
@@ -929,7 +935,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -942,7 +948,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -954,7 +960,7 @@ const TenantsTab = memo((props) => {
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "flex",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
height: 30,
|
||||
}}
|
||||
>
|
||||
@@ -976,7 +982,7 @@ const TenantsTab = memo((props) => {
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
/>
|
||||
@@ -987,7 +993,7 @@ const TenantsTab = memo((props) => {
|
||||
) : parentOrg?.id?.length > 0 ? (
|
||||
<ListItem
|
||||
style={{
|
||||
backgroundColor: "#1A1A1A",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
display: "table-row",
|
||||
padding: 8,
|
||||
verticalAlign: "middle",
|
||||
@@ -1095,7 +1101,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "10px",
|
||||
whiteSpace: "nowrap",
|
||||
}}
|
||||
primary={index === 1 ? "Parent Organization not found or May be you are not part of parent org. Please contact support@shuffler.io." : null}
|
||||
primary={index === 1 ? `Parent Organization not found or May be you are not part of parent org. Please contact ${supportEmail}` : null}
|
||||
colSpan={index === 0 ? 5 : undefined}
|
||||
/>
|
||||
))}
|
||||
@@ -1123,17 +1129,15 @@ const TenantsTab = memo((props) => {
|
||||
marginTop: 20,
|
||||
}}
|
||||
>
|
||||
<h3
|
||||
<Typography
|
||||
variant='h6'
|
||||
color="textPrimary"
|
||||
style={{
|
||||
margin: 0,
|
||||
fontSize: '1.2rem',
|
||||
fontWeight: 'bold',
|
||||
letterSpacing: '1px',
|
||||
color: "#ffffff"
|
||||
}}
|
||||
>
|
||||
Sub Organizations of the Current Organization ({subOrgs.length})
|
||||
</h3>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
{/* <Divider
|
||||
@@ -1144,7 +1148,7 @@ const TenantsTab = memo((props) => {
|
||||
}}
|
||||
/> */}
|
||||
|
||||
<div style={{borderRadius: 4, marginTop: 24, border: "1px solid #494949", width: "100%", overflowX: "auto", paddingBottom: 0 }}>
|
||||
<div style={{borderRadius: 4, marginTop: 24, border: theme.palette.defaultBorder, width: "100%", overflowX: "auto", paddingBottom: 0 }}>
|
||||
<List
|
||||
style={{
|
||||
width: '100%',
|
||||
@@ -1188,7 +1192,7 @@ const TenantsTab = memo((props) => {
|
||||
display: "table-cell",
|
||||
padding: "0px 8px 8px 8px",
|
||||
textAlign: "center",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -1214,7 +1218,7 @@ const TenantsTab = memo((props) => {
|
||||
display: "table-cell",
|
||||
padding: "0px 8px 8px 8px",
|
||||
textAlign: "center",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}} />
|
||||
<ListItemText
|
||||
@@ -1226,7 +1230,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
textAlign: "center",
|
||||
}} />
|
||||
@@ -1237,7 +1241,7 @@ const TenantsTab = memo((props) => {
|
||||
minWidth: 100,
|
||||
maxWidth: 100,
|
||||
display: "table-cell",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
padding: "0px 8px 8px 8px",
|
||||
}}
|
||||
/>
|
||||
@@ -1251,7 +1255,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -1264,7 +1268,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -1290,9 +1294,13 @@ const TenantsTab = memo((props) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
var bgColor = themeMode === "dark" ? "#212121" : "#FFFFFF";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = themeMode === "dark" ? "#1A1A1A" : "#EAEAEA";
|
||||
}
|
||||
|
||||
return (
|
||||
<ListItem key={index} style={{ backgroundColor: index % 2 === 0 ? '#1A1A1A' : '#212121', width: "100%", borderBottomLeftRadius: 8, display:'table-row', borderBottomRightRadius: 8 }}>
|
||||
<ListItem key={index} style={{ backgroundColor: bgColor, width: "100%", borderBottomLeftRadius: 8, display:'table-row', borderBottomRightRadius: 8 }}>
|
||||
<ListItemText primary={<img alt={data?.name} src={data.image || theme.palette.defaultImage} style={imageStyle} />} style={{ width: 100,
|
||||
minWidth: 100,
|
||||
maxWidth: 100,
|
||||
@@ -1374,17 +1382,15 @@ const TenantsTab = memo((props) => {
|
||||
/>
|
||||
|
||||
<div style={{ textAlign: 'left', width: '100%', padding: '10px', marginTop: 20 }}>
|
||||
<h3
|
||||
<Typography
|
||||
variant='h6'
|
||||
color="textPrimary"
|
||||
style={{
|
||||
margin: 0,
|
||||
fontSize: '1.2rem',
|
||||
fontWeight: 'bold',
|
||||
letterSpacing: '1px',
|
||||
color: "#ffffff"
|
||||
}}
|
||||
>
|
||||
All Tenants
|
||||
</h3>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
{/* <Divider
|
||||
@@ -1398,7 +1404,7 @@ const TenantsTab = memo((props) => {
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.defaultBorder,
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
@@ -1448,7 +1454,7 @@ const TenantsTab = memo((props) => {
|
||||
display: "table-cell",
|
||||
padding: "0px 8px 8px 8px",
|
||||
textAlign: "center",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -1475,7 +1481,7 @@ const TenantsTab = memo((props) => {
|
||||
display: "table-cell",
|
||||
padding: "0px 8px 8px 8px",
|
||||
textAlign: "center",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -1488,7 +1494,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
textAlign: "center",
|
||||
}}
|
||||
@@ -1500,7 +1506,7 @@ const TenantsTab = memo((props) => {
|
||||
minWidth: 100,
|
||||
maxWidth: 100,
|
||||
display: "table-cell",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
padding: "0px 8px 8px 8px",
|
||||
}}
|
||||
/>
|
||||
@@ -1514,7 +1520,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -1527,7 +1533,7 @@ const TenantsTab = memo((props) => {
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
/>
|
||||
@@ -1590,6 +1596,11 @@ const TenantsTab = memo((props) => {
|
||||
}
|
||||
}
|
||||
|
||||
var bgColor = themeMode === "dark" ? "#212121" : "#FFFFFF";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = themeMode === "dark" ? "#1A1A1A" : "#EAEAEA";
|
||||
}
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
key={index}
|
||||
@@ -1597,7 +1608,7 @@ const TenantsTab = memo((props) => {
|
||||
display: "table-row",
|
||||
verticalAlign: "middle",
|
||||
padding: 8,
|
||||
backgroundColor: index % 2 === 0 ? "#1A1A1A" : "#212121",
|
||||
backgroundColor: bgColor,
|
||||
borderBottomLeftRadius:
|
||||
userdata?.orgs?.length - 1 === index ? 8 : 0,
|
||||
borderBottomRightRadius:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect, useContext, memo } from "react";
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import {
|
||||
FormControl,
|
||||
InputLabel,
|
||||
@@ -35,7 +35,7 @@ import {
|
||||
import ModeEditOutlineOutlinedIcon from '@mui/icons-material/ModeEditOutlineOutlined';
|
||||
import ContentCopyOutlinedIcon from '@mui/icons-material/ContentCopyOutlined';
|
||||
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
const ITEM_HEIGHT = 48;
|
||||
const ITEM_PADDING_TOP = 8;
|
||||
const MenuProps = {
|
||||
@@ -75,12 +75,17 @@ const UserManagmentTab = memo((props) => {
|
||||
const [logsViewModal, setLogsViewModal] = React.useState(false);
|
||||
const [ipSelected, setIpSelected] = React.useState("");
|
||||
const [userLogViewing, setUserLogViewing] = React.useState({});
|
||||
const { themeMode, supportEmail, brandColor } = useContext(Context);
|
||||
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedOrganization?.mfa_required !== MFARequired) {
|
||||
setMFARequired(selectedOrganization?.mfa_required);
|
||||
}
|
||||
}, [selectedOrganization]);
|
||||
|
||||
useEffect(() => { if(users?.length === 0){
|
||||
getUsers();
|
||||
} }, []);
|
||||
@@ -363,7 +368,7 @@ const UserManagmentTab = memo((props) => {
|
||||
toast("Failed to deactivate user: " + responseJson.reason);
|
||||
} else if (responseJson.success === false) {
|
||||
toast(
|
||||
"Failed to deactivate user. Please contact support@shuffler.io if this persists.",
|
||||
`Failed to deactivate user. Please contact ${supportEmail} if this persists.`,
|
||||
);
|
||||
} else {
|
||||
toast("Changed activation for user " + data.id);
|
||||
@@ -602,7 +607,7 @@ const UserManagmentTab = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<Typography style={{ color: "white", textTransform: 'none', fontSize: 24 }}>
|
||||
<Typography variant="h5" style={{ textTransform: 'none', fontSize: 24 }}>
|
||||
Add user
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
@@ -619,7 +624,7 @@ const UserManagmentTab = memo((props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
@@ -682,17 +687,17 @@ const UserManagmentTab = memo((props) => {
|
||||
</div>
|
||||
{loginInfo}
|
||||
</DialogContent>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'flex-end', p: 2, backgroundColor: "#212121" }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'flex-end', p: 2, backgroundColor: theme.palette.platformColor }}>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#ff8544", marginRight: 5 }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, marginRight: 5, color: theme.palette.primary.main }}
|
||||
onClick={() => setModalOpen(false)}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#1a1a1a", backgroundColor: "#ff8544" }}
|
||||
color="primary"
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16,}}
|
||||
onClick={() => {
|
||||
if (isCloud) {
|
||||
inviteUser(modalUser);
|
||||
@@ -700,7 +705,6 @@ const UserManagmentTab = memo((props) => {
|
||||
submitUser(modalUser);
|
||||
}
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
@@ -751,7 +755,7 @@ const UserManagmentTab = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<DialogTitle style={{ maxWidth: "800px", width: "100%", textAlign: "center", margin: "auto", backgroundColor: theme?.palette?.DialogStyle?.backgroundColor}}>
|
||||
<span style={{ color: "white", backgroundColor: theme?.palette?.DialogStyle?.backgroundColor }}>
|
||||
<span style={{ color: theme.palette.text.primary, backgroundColor: theme?.palette?.DialogStyle?.backgroundColor }}>
|
||||
<EditIcon style={{ marginTop: 5 }} /> Editing {selectedUser.username}
|
||||
</span>
|
||||
</DialogTitle>
|
||||
@@ -845,9 +849,10 @@ const UserManagmentTab = memo((props) => {
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
}}
|
||||
/>
|
||||
<div style={{ margin: "auto", maxWidth: 450 }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', margin: "auto", maxWidth: 450 }}>
|
||||
<div style={{ display: "flex", justifyContent: "space-between", width: "100%" }}>
|
||||
<Button
|
||||
style={{textTransform: 'none', fontSize: 16}}
|
||||
style={{textTransform: 'none', fontSize: 16, whiteSpace: 'nowrap', textWrap: 'nowarp'}}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
disabled={selectedUser.username === userdata.username}
|
||||
@@ -859,7 +864,7 @@ const UserManagmentTab = memo((props) => {
|
||||
{selectedUser.active ? "Delete from org" : "Delete from org"}
|
||||
</Button>
|
||||
<Button
|
||||
style={{ textTransform: 'none', fontSize: 16 }}
|
||||
style={{ textTransform: 'none', fontSize: 16, whiteSpace: 'nowrap', textWrap: 'nowarp', }}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
disabled={
|
||||
@@ -880,7 +885,7 @@ const UserManagmentTab = memo((props) => {
|
||||
}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
style={{textTransform: 'none', fontSize: 16}}
|
||||
style={{textTransform: 'none', fontSize: 16, whiteSpace: 'nowrap', textWrap: 'nowarp', }}
|
||||
>
|
||||
{selectedUser.mfa_info !== undefined &&
|
||||
selectedUser.mfa_info !== null &&
|
||||
@@ -888,6 +893,7 @@ const UserManagmentTab = memo((props) => {
|
||||
? "Disable 2FA"
|
||||
: "Enable 2FA"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{isCloud && userdata.support && selectedUser.id !== userdata.id ? (
|
||||
<Button
|
||||
@@ -897,6 +903,8 @@ const UserManagmentTab = memo((props) => {
|
||||
marginTop: 50,
|
||||
border: "1px solid #d52b2b",
|
||||
textTransform: "none",
|
||||
whiteSpace: 'nowrap',
|
||||
textWrap: 'nowarp',
|
||||
color:
|
||||
showDeleteAccountTextbox === true &&
|
||||
deleteAccountText?.length > 0 &&
|
||||
@@ -1269,23 +1277,23 @@ const UserManagmentTab = memo((props) => {
|
||||
) : null
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121',borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949", }}>
|
||||
<div style={{ width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: theme.palette.platformColor, borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949", }}>
|
||||
{modalView}
|
||||
{editUserModal}
|
||||
{logview}
|
||||
<div style={{ height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
||||
<div style={{ height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin' }}>
|
||||
<div style={{display: 'flex', justifyContent: 'space-between'}}>
|
||||
<div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<h2 style={{ marginBottom: 8, marginTop: 0, color: "#FFFFFF" }}>User Management</h2>
|
||||
<span style={{ color: "#9E9E9E" }}>
|
||||
<Typography variant="h5" style={{ marginBottom: 8, marginTop: 0, }}>User Management</Typography>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
Add, edit, distribute or remove users from your organization.{" "}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/admin?admin_tab=sso"
|
||||
style={{ color: "#FF8444" }}
|
||||
style={{ color: theme.palette.linkColor }}
|
||||
>
|
||||
Configure SSO
|
||||
</a>
|
||||
@@ -1296,15 +1304,15 @@ const UserManagmentTab = memo((props) => {
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="/docs/organizations#user_management"
|
||||
style={{ color: "#FF8444" }}
|
||||
style={{ color: theme.palette.linkColor }}
|
||||
>
|
||||
learn more about users
|
||||
</a>
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
<div />
|
||||
<Button
|
||||
style={{ color: "#1a1a1a", backgroundColor: "#ff8544",fontSize: 16, textTransform: 'none', borderRadius: 4, width: 162, height: 40, boxShadow: 'none' }}
|
||||
style={{ fontSize: 16, textTransform: 'none', borderRadius: 4, width: 162, height: 40, boxShadow: 'none' }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => setModalOpen(true)}
|
||||
@@ -1312,9 +1320,9 @@ const UserManagmentTab = memo((props) => {
|
||||
Add user
|
||||
</Button>
|
||||
<Button
|
||||
style={{ backgroundColor: "#2F2F2F", boxShadow: 'none', borderRadius: 4, width: 81, height: 40, marginLeft: 16, marginRight: 15 }}
|
||||
style={{ boxShadow: 'none', borderRadius: 4, width: 81, height: 40, marginLeft: 16, marginRight: 15 }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
color="secondary"
|
||||
onClick={() => getUsers()}
|
||||
>
|
||||
<CachedIcon />
|
||||
@@ -1334,7 +1342,7 @@ const UserManagmentTab = memo((props) => {
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
border: theme.palette.defaultBorder,
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
@@ -1350,7 +1358,7 @@ const UserManagmentTab = memo((props) => {
|
||||
paddingBottom: 0,
|
||||
}}
|
||||
>
|
||||
<ListItem style={{ width: "100%", padding: "10px 10px 10px 0px", verticalAlign: 'middle', borderBottom: "1px solid #494949", display: "table-row" }}>
|
||||
<ListItem style={{ width: "100%", padding: "10px 10px 10px 0px", verticalAlign: 'middle', borderBottom: theme.palette.defaultBorder, display: "table-row" }}>
|
||||
{["Username", /*"API Key",*/ "Role", /*"Active",*/ "Type", "MFA", ...(selectedOrganization?.child_orgs?.length > 0 ? ["Suborgs"]: []), "Actions", "Last Login"].map((header, index) => (
|
||||
<ListItemText
|
||||
key={index}
|
||||
@@ -1360,7 +1368,7 @@ const UserManagmentTab = memo((props) => {
|
||||
padding: index === 0 ? "0px 8px 8px 15px": "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
borderBottom: theme.palette.defaultBorder,
|
||||
position: "sticky",
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
@@ -1373,7 +1381,7 @@ const UserManagmentTab = memo((props) => {
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "table-row",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
}}
|
||||
>
|
||||
{Array(9)
|
||||
@@ -1390,7 +1398,7 @@ const UserManagmentTab = memo((props) => {
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
height: "20px",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
@@ -1401,9 +1409,9 @@ const UserManagmentTab = memo((props) => {
|
||||
))
|
||||
): users === 0 ? null
|
||||
: users?.map((data, index) => {
|
||||
var bgColor = "#212121";
|
||||
var bgColor = themeMode === "dark" ? "#212121" : "#FFFFFF";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = "#1A1A1A";
|
||||
bgColor = themeMode === "dark" ? "#1A1A1A" : "#EAEAEA";
|
||||
}
|
||||
|
||||
const timeNow = new Date().getTime();
|
||||
@@ -1434,8 +1442,7 @@ const UserManagmentTab = memo((props) => {
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
textDecoration: "underline",
|
||||
textDecorationColor: "#F76742",
|
||||
color: "#F76742",
|
||||
color: theme.palette.linkColor,
|
||||
}}
|
||||
onClick={() => {
|
||||
setLogsViewModal(true);
|
||||
@@ -1465,7 +1472,7 @@ const UserManagmentTab = memo((props) => {
|
||||
maxWidth: 150,
|
||||
minWidth: 100,
|
||||
width: 'auto',
|
||||
color: "#FF8444",
|
||||
color: theme.palette.primary.main,
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
@@ -1522,8 +1529,8 @@ const UserManagmentTab = memo((props) => {
|
||||
setUser(data.id, "role", e.target.value);
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: "#1A1A1A",
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.textColor,
|
||||
height: "50px",
|
||||
borderRadius: "4px",
|
||||
marginTop: "8px",
|
||||
@@ -1542,27 +1549,35 @@ const UserManagmentTab = memo((props) => {
|
||||
>
|
||||
<MenuItem
|
||||
sx={{
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: "white",
|
||||
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.textColor,
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor,
|
||||
},
|
||||
}}
|
||||
value={"admin"}
|
||||
>
|
||||
Org Admin
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
style={{
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: "white",
|
||||
sx={{
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.textColor,
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor,
|
||||
},
|
||||
}}
|
||||
value={"user"}
|
||||
>
|
||||
Org User
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
style={{
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: "white",
|
||||
sx={{
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.textColor,
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor,
|
||||
},
|
||||
}}
|
||||
value={"org-reader"}
|
||||
>
|
||||
@@ -1664,7 +1679,20 @@ const UserManagmentTab = memo((props) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<img src="/icons/editIcon.svg" alt="edit icon" style={{width: 24, height: 24}} />
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.1038 4.66848C16.3158 4.45654 16.5674 4.28843 16.8443 4.17373C17.1212 4.05903 17.418 4 17.7177 4C18.0174 4 18.3142 4.05903 18.5911 4.17373C18.868 4.28843 19.1196 4.45654 19.3315 4.66848C19.5435 4.88041 19.7116 5.13201 19.8263 5.40891C19.941 5.68582 20 5.9826 20 6.28232C20 6.58204 19.941 6.87882 19.8263 7.15573C19.7116 7.43263 19.5435 7.68423 19.3315 7.89617L8.43807 18.7896L4 20L5.21038 15.5619L16.1038 4.66848Z"
|
||||
stroke={themeMode=== "dark" ? "#F1F1F1" : "#333"}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</IconButton>
|
||||
{/* <Button
|
||||
onClick={() => {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
|
||||
import { toast } from "react-toastify"
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import { useNavigate, Link, useParams } from "react-router-dom";
|
||||
import AppSearchButtons from "../components/AppSearchButtons.jsx";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import RenderCytoscape from "../components/RenderCytoscape.jsx";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import {
|
||||
Button,
|
||||
Typography,
|
||||
@@ -72,7 +73,8 @@ const WorkflowTemplatePopup = (props) => {
|
||||
const [loadingWorkflow, setLoadingWorkflow] = React.useState(false)
|
||||
const [workflow, setWorkflow] = useState(inputWorkflow !== undefined && inputWorkflow !== null && inputWorkflow.id !== undefined && inputWorkflow.id !== null && inputWorkflow.id !== "" ? inputWorkflow : {})
|
||||
const [_, setUpdate] = useState(0)
|
||||
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode)
|
||||
const fetchWorkflow = (id) => {
|
||||
if (id === undefined || id === null || id === "") {
|
||||
return
|
||||
@@ -549,12 +551,10 @@ const WorkflowTemplatePopup = (props) => {
|
||||
open={modalOpen}
|
||||
onClose={handleClose}
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: "black",
|
||||
color: "white",
|
||||
minWidth: isHomePage ? null : isMobile ? 300 : 750,
|
||||
maxWidth: isHomePage ? null : isMobile ? 300 : 750,
|
||||
paddingTop: isMobile ? null : 75,
|
||||
sx: {
|
||||
backgroundColor: theme.palette.drawer.backgroundColor,
|
||||
minWidth: isHomePage ? null : isMobile ? "300px" : "750px",
|
||||
maxWidth: isHomePage ? null : isMobile ? "300px" : "750px",
|
||||
itemAlign: "center",
|
||||
},
|
||||
}}
|
||||
@@ -571,7 +571,7 @@ const WorkflowTemplatePopup = (props) => {
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
<DialogContent style={{marginTop: 0, marginLeft: isHomePage ? null : isMobile ? null : 75, maxWidth: 470, marginTop: 20 }}>
|
||||
<DialogContent style={{paddingTop: isMobile ? null : "75px", backgroundColor: theme.palette.drawer.backgroundColor, marginTop: 0, paddingLeft: isHomePage ? null : isMobile ? null : 75, maxWidth: "100%",}}>
|
||||
<Typography variant="h4" style={{ fontSize: isMobile ? 20 : null}}>
|
||||
<b>Configure Workflow</b>
|
||||
</Typography>
|
||||
@@ -790,7 +790,7 @@ const WorkflowTemplatePopup = (props) => {
|
||||
width: isHomePage? isMobile ? null : "100%" : "99%",
|
||||
borderRadius: 8,
|
||||
textTransform: "none",
|
||||
backgroundColor: isHomePage ? null : theme.palette.inputColor,
|
||||
backgroundColor: isHomePage ? null : theme.palette.platformColor,
|
||||
border: borderStyle,
|
||||
cursor: isActive ? errorMessage !== "" ? "not-allowed" : "pointer" : "pointer",
|
||||
position: "relative",
|
||||
@@ -878,7 +878,7 @@ const WorkflowTemplatePopup = (props) => {
|
||||
|
||||
</div>
|
||||
<div style={{ marginLeft: 20, overflow: "hidden", maxHeight: 30, marginTop: visualOnly ? 12 : showTryitOut && !isActive ? 8 : 23, }}>
|
||||
<Typography variant="body1" style={{ marginTop: parsedDescription.length === 0 ? 10 : 0, fontSize: isMobile ? 13 : 16, fontWeight: isHomePage ? 600 : null, textTransform: 'capitalize', color: isHomePage ? "var(--White-text, #F1F1F1)" : "rgba(241, 241, 241, 1)"}} >
|
||||
<Typography variant="body1" color="textPrimary" style={{ marginTop: parsedDescription.length === 0 ? 10 : 0, fontSize: isMobile ? 13 : 16, fontWeight: isHomePage ? 600 : null, textTransform: 'capitalize', }} >
|
||||
<b>{parsedTitle}</b>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useContext } from "react";
|
||||
import React from "react";
|
||||
import {
|
||||
Typography,
|
||||
@@ -13,6 +13,8 @@ import { makeStyles } from "@mui/styles";
|
||||
import { Link } from "react-router-dom";
|
||||
import theme from "../theme.jsx";
|
||||
import { toast } from "react-toastify";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import { getTheme } from "../theme.jsx";
|
||||
|
||||
const useStyles = makeStyles({
|
||||
notchedOutline: {
|
||||
@@ -26,6 +28,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
const classes = useStyles();
|
||||
const [show2faSetup, setShow2faSetup] = React.useState(false);
|
||||
const [autoPrivision, setAutoProvision] = React.useState(selectedOrganization?.sso_config?.auto_provision)
|
||||
const [roleRequired, setRoleRequired] = React.useState(selectedOrganization?.sso_config?.role_required || false);
|
||||
const [showOpenIdCred, setShowOpenIdCred] = React.useState(false);
|
||||
const [showSamlCred, setShowSamlCred] = React.useState(false);
|
||||
const [ssoEntrypoint, setSsoEntrypoint] = React.useState(
|
||||
@@ -84,6 +87,9 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
: selectedOrganization.sso_config.openid_token
|
||||
)
|
||||
|
||||
const { themeMode, supportEmail, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
useEffect(()=>{
|
||||
|
||||
if (openidClientSecret !== selectedOrganization?.sso_config?.client_secret) {
|
||||
@@ -116,12 +122,17 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
if (autoPrivision !== selectedOrganization?.sso_config?.auto_provision) {
|
||||
setAutoProvision(selectedOrganization?.sso_config?.auto_provision)
|
||||
}
|
||||
|
||||
if (roleRequired !== selectedOrganization?.sso_config?.role_required) {
|
||||
setRoleRequired(selectedOrganization?.sso_config?.role_required)
|
||||
}
|
||||
|
||||
},[selectedOrganization])
|
||||
|
||||
const orgSaveButton = (
|
||||
<Tooltip title="Save any unsaved data" placement="bottom">
|
||||
<Button
|
||||
style={{ width: 244, height: 51, flex: 1, textTransform: 'capitalize', padding: "16px, 24px, 16px, 24px", borderRadius: 4, backgroundColor: "#ff8544", color: "#1a1a1a", fontSize: 16, }}
|
||||
style={{ width: 244, height: 51, flex: 1, textTransform: 'capitalize', padding: "16px, 24px, 16px, 24px", borderRadius: 4, fontSize: 16, }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={
|
||||
@@ -158,6 +169,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
openid_token: openidToken,
|
||||
SSORequired: SSORequired,
|
||||
auto_provision: autoPrivision,
|
||||
role_required: roleRequired,
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -206,6 +218,21 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
}
|
||||
};
|
||||
|
||||
const handleChangeRoleRequired = (event) => {
|
||||
if (
|
||||
openidAuthorization?.length === 0 &&
|
||||
openidToken?.length === 0
|
||||
) {
|
||||
toast.error(
|
||||
"Please fill in fields for OpenID connect before continuing. "
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
setRoleRequired((prev)=> !prev);
|
||||
toast.info("Toggled Role Required. Remember to save.");
|
||||
}
|
||||
}
|
||||
|
||||
const HandleTestSSO = () => {
|
||||
const url = `${globalUrl}/api/v1/orgs/${selectedOrganization?.id}/change`;
|
||||
const data = {
|
||||
@@ -227,7 +254,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
toast.error(
|
||||
"Failed to test SSO. Please try again later or contact support@shuffler.io if issue persists.",
|
||||
`Failed to test SSO. Please try again later or contact ${supportEmail} if issue persists.`,
|
||||
{ duration: 3000 }
|
||||
);
|
||||
return null;
|
||||
@@ -264,10 +291,10 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%", height: "100%",boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121', borderRadius: '16px', }}>
|
||||
<div style={{ height: "100%", width: "100%", overflowX: 'hidden', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}} >
|
||||
<div style={{ width: "100%", height: "100%",boxSizing: 'border-box', padding: "27px 10px 19px 27px", backgroundColor: theme.palette.platformColor , borderRadius: '16px', }}>
|
||||
<div style={{ height: "100%", width: "100%", overflowX: 'hidden', scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}} >
|
||||
<div style={{ width: "100%", overflowX: 'hidden', maxWidth: 883}}>
|
||||
<Typography style={{ width: "100%", fontWeight: 'bold', fontSize: 24}}>
|
||||
<Typography variant="h5" style={{ width: "100%", fontWeight: 500, fontSize: 24}}>
|
||||
SSO Configuration
|
||||
</Typography>
|
||||
<div
|
||||
@@ -282,7 +309,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="textSecondary"
|
||||
style={{ marginTop: 5, marginBottom: 5, color: "rgba(158, 158, 158, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400 }}
|
||||
style={{ marginTop: 5, marginBottom: 5, fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400 }}
|
||||
>
|
||||
Make SAML SSO or OpenID Authentication Required or Optional for Your Organization.
|
||||
</Typography>
|
||||
@@ -312,7 +339,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="textSecondary"
|
||||
style={{ marginTop: 5, marginBottom: 5, color: "rgba(158, 158, 158, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400 }}
|
||||
style={{ marginTop: 5, marginBottom: 5, fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400 }}
|
||||
>
|
||||
Auto-provisioning of users in SSO. By default, users are auto-provisioned in SSO when they login. If you enable this, no new user will be added in your organization when they login via SSO.
|
||||
</Typography>
|
||||
@@ -327,6 +354,36 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
justifyContent: 'flex-start',
|
||||
marginTop: 30
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="textSecondary"
|
||||
style={{ marginTop: 5, marginBottom: 5, color: "rgba(158, 158, 158, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400 }}
|
||||
>
|
||||
Restrict user login to SSO if no valid role is assigned by the SSO provider. When enabled, users will not be allowed to log in via SSO if their assigned role doesn't matches one of the following: shuffle-user, shuffle-admin, or shuffle-org-reader. Currently, available for OpenId Connect only.
|
||||
<a href="https://shuffler.io/docs/extensions#how-to-assign-a-role-to-a-new-user-from-an-sso-provider-(openid-connect)-in-shuffle" target="_blank" style={{ color: theme.palette.linkColor }}> Learn more</a>
|
||||
</Typography>
|
||||
<div>
|
||||
<Switch
|
||||
checked={roleRequired}
|
||||
onChange={handleChangeRoleRequired}
|
||||
sx={{marginBottom: 0.6, marginTop: 0.6}}
|
||||
name="onOffSwitch"
|
||||
color="primary"
|
||||
title="Disable auto-provisioning of users in SSO"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -338,7 +395,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
paddingBottom: 10,
|
||||
}}
|
||||
>
|
||||
<Typography style={{color: "rgba(158, 158, 158, 1)", margin: "5px 0px 5px 0px", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }}>
|
||||
<Typography variant="body2" color="textSecondary" style={{ margin: "5px 0px 5px 0px", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }}>
|
||||
You can test your SSO configuration by clicking the button below.
|
||||
Before testing, ensure you have set Open ID Connect or SAML SSO
|
||||
credentials.
|
||||
@@ -359,7 +416,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
style={{ width: 100, textTransform: "none", margin: "10px 10px 10px 0px" }}
|
||||
style={{ width: 100, textTransform: "none", margin: "10px 10px 10px 0px", whiteSpace: "nowrap" }}
|
||||
disabled={
|
||||
!(
|
||||
ssoEntrypoint?.length > 0 ||
|
||||
@@ -377,28 +434,28 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
</div>
|
||||
<Grid item xs={12} sx={{marginTop: 2}}>
|
||||
<span style={{ display: "flex", flexDirection: "column" }}>
|
||||
<Typography style={{ textAlign: "left", color: "rgba(241, 241, 241, 1)", fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 24, fontWeight: "bold", }}>OpenID connect</Typography>
|
||||
<span style={{ marginTop: 8, color: "rgba(158, 158, 158, 1)", fontSize: 16, fontWeight: 400 }}>
|
||||
<Typography variant="h5" color="textPrimary" style={{ textAlign: "left", fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 24, fontWeight: 500, }}>OpenID connect</Typography>
|
||||
<span style={{ marginTop: 8, color: theme.palette.text.secondary, fontSize: 16, fontWeight: 400 }}>
|
||||
Configure and Authorize SAML / SSO or OpenID connect. {" "}
|
||||
<a
|
||||
target="_blank"
|
||||
href="/docs/extensions#single-signon"
|
||||
style={{ color: "rgba(255, 132, 68, 1)" }}
|
||||
style={{ color: theme.palette.linkColor }}
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
<Typography style={{ textAlign: "left", fontSize: 16, marginTop: 8, color: "rgba(158, 158, 158, 1)", fontWeight: 400 }}>
|
||||
IdP URL for Shuffle OpenID: <Link to={`${globalUrl}/api/v1/login_openid`} target="_blank" style={{ color: "rgba(241, 241, 241, 1)", textDecoration: "none", fontSize: 16,}}>{`${globalUrl}/api/v1/login_openid`}</Link>
|
||||
<Typography variant="body2" color="tehttp://localhost:5002/api/v1/login_openidxtSecondary" style={{ textAlign: "left", fontSize: 16, marginTop: 8, fontWeight: 400 }}>
|
||||
IdP URL for Shuffle OpenID: <Link to={`${globalUrl}/api/v1/login_openid`} target="_blank" style={{ color: theme.palette.text.secondary, textDecoration: "none", fontSize: 16,}}>{`${globalUrl}/api/v1/login_openid`}</Link>
|
||||
</Typography>
|
||||
<div style={{ display: 'flex', marginTop: 10, }}>
|
||||
<Typography
|
||||
color="textSecondary"
|
||||
style={{
|
||||
textAlign: "left",
|
||||
fontSize: 16,
|
||||
marginTop: 8,
|
||||
color: "rgba(158, 158, 158, 1)",
|
||||
fontWeight: 400,
|
||||
}}
|
||||
>
|
||||
@@ -409,20 +466,19 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
onChange={(e) => setShowOpenIdCred(e.target.checked)}
|
||||
name="showOpenIdCred"
|
||||
color="primary"
|
||||
style={{ color: "rgba(255, 255, 255, 1)", }}
|
||||
/>
|
||||
</div>
|
||||
<Grid container style={{ marginTop: 8, }} spacing={2}>
|
||||
<Grid item xs={6} style={{}}>
|
||||
<span>
|
||||
<Typography style={{ color: "rgba(255, 255, 255, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, fontSize: 16 }}>Client ID</Typography>
|
||||
<Typography style={{ fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, }}>Client ID</Typography>
|
||||
<TextField
|
||||
required
|
||||
style={{
|
||||
flex: "1",
|
||||
marginTop: "5px",
|
||||
marginRight: "15px",
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
multiline={true}
|
||||
@@ -440,11 +496,11 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
borderRadius: 4,
|
||||
borderRadius: theme.palette.textFieldStyle.borderRadius,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -452,14 +508,14 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
</Grid>
|
||||
<Grid item xs={6} style={{}}>
|
||||
<span>
|
||||
<Typography style={{ color: "rgba(255, 255, 255, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, fontSize: 16 }}>Client Secret</Typography>
|
||||
<Typography style={{ fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, }}>Client Secret</Typography>
|
||||
<TextField
|
||||
required
|
||||
style={{
|
||||
flex: "1",
|
||||
marginTop: "5px",
|
||||
marginRight: "15px",
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
type={showOpenIdCred ? "text" : "password"}
|
||||
@@ -480,11 +536,11 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
borderRadius: 4,
|
||||
borderRadius: theme.palette.textFieldStyle.borderRadius,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -494,14 +550,14 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
<Grid container style={{ marginTop: 10, }} spacing={2}>
|
||||
<Grid item xs={6} style={{}}>
|
||||
<span>
|
||||
<Typography style={{ color: "rgba(255, 255, 255, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, fontSize: 16 }}>Authorization URL</Typography>
|
||||
<Typography style={{ fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, fontSize: 16 }}>Authorization URL</Typography>
|
||||
<TextField
|
||||
required
|
||||
style={{
|
||||
flex: "1",
|
||||
marginTop: "5px",
|
||||
marginRight: "15px",
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
type={showOpenIdCred ? "text" : "password"}
|
||||
@@ -522,7 +578,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
@@ -534,14 +590,14 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
</Grid>
|
||||
<Grid item xs={6} style={{}}>
|
||||
<span>
|
||||
<Typography style={{ color: "rgba(255, 255, 255, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, fontSize: 16 }}>Token URL</Typography>
|
||||
<Typography style={{ fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, }}>Token URL</Typography>
|
||||
<TextField
|
||||
required
|
||||
style={{
|
||||
flex: "1",
|
||||
marginTop: "5px",
|
||||
marginRight: "15px",
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
type={showOpenIdCred ? "text" : "password"}
|
||||
@@ -562,7 +618,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color:theme.palette.textFieldStyle.color,
|
||||
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
@@ -577,17 +633,17 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
{/**/}
|
||||
{/*isCloud ? null : */}
|
||||
<Grid item xs={12} sx={{ marginTop: 3.5 }} >
|
||||
<Typography variant="h4" style={{ textAlign: "left", color: "rgba(241, 241, 241, 1)", fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 24, fontWeight: 600, }}>SAML SSO (v1.1)</Typography>
|
||||
<Typography variant="body2" style={{ textAlign: "left", marginTop: 8, color: "rgba(241, 241, 241, 1)", fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 16, fontWeight: 400, color: "rgba(158, 158, 158, 1)" }} color="textSecondary">
|
||||
IdP URL for Shuffle SAML/SSO: <Link to={`${globalUrl}/api/v1/login_sso`} target="_blank" style={{ color: "rgba(241, 241, 241, 1)", textDecoration: "none" }}>{`${globalUrl}/api/v1/login_sso`}</Link>
|
||||
<Typography variant="h5" color="textPrimary" style={{ textAlign: "left", fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 24, fontWeight: 500, }}>SAML SSO (v1.1)</Typography>
|
||||
<Typography variant="body2" color="textSecondary" style={{ textAlign: "left", marginTop: 8, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 16, fontWeight: 400, }}>
|
||||
IdP URL for Shuffle SAML/SSO: <Link to={`${globalUrl}/api/v1/login_sso`} target="_blank" style={{ color: theme.palette.text.secondary, textDecoration: "none" }}>{`${globalUrl}/api/v1/login_sso`}</Link>
|
||||
</Typography>
|
||||
<div style={{ display: 'flex', marginTop: 10, }}>
|
||||
<Typography
|
||||
color="textSecondary"
|
||||
style={{
|
||||
textAlign: "left",
|
||||
fontSize: 16,
|
||||
marginTop: 8,
|
||||
color: "rgba(158, 158, 158, 1)",
|
||||
fontWeight: 400,
|
||||
}}
|
||||
>
|
||||
@@ -598,20 +654,19 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
onChange={(e) => setShowSamlCred(e.target.checked)}
|
||||
name="showSamlCred"
|
||||
color="primary"
|
||||
style={{ color: "rgba(255, 255, 255, 1)", }}
|
||||
/>
|
||||
</div>
|
||||
<Grid container style={{ marginTop: 10, }} spacing={2}>
|
||||
<Grid item xs={6} style={{}}>
|
||||
<span>
|
||||
<Typography style={{ color: "rgba(255, 255, 255, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, fontSize: 16 }}>SSO Entrypoint (IdP)</Typography>
|
||||
<Typography style={{ fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, }}>SSO Entrypoint (IdP)</Typography>
|
||||
<TextField
|
||||
required
|
||||
style={{
|
||||
flex: "1",
|
||||
marginTop: "5px",
|
||||
marginRight: "15px",
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
type={showSamlCred ? "text" : "password"}
|
||||
@@ -632,7 +687,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
@@ -644,14 +699,14 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
</Grid>
|
||||
<Grid item xs={6} style={{}}>
|
||||
<span>
|
||||
<Typography style={{ color: "rgba(255, 255, 255, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, fontSize: 16 }}>SSO Certificate (X509)</Typography>
|
||||
<Typography style={{ fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400, fontSize: 16 }}>SSO Certificate (X509)</Typography>
|
||||
<TextField
|
||||
required
|
||||
style={{
|
||||
flex: "1",
|
||||
marginTop: "5px",
|
||||
marginRight: "15px",
|
||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||
backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor: theme.palette.inputColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
type={showSamlCred ? "text" : "password"}
|
||||
@@ -672,7 +727,7 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
||||
fontWeight: 400,
|
||||
fontSize: 16,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import React, { createContext, useState, useEffect } from 'react';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
|
||||
export const Context = createContext();
|
||||
|
||||
export const AppContext = (props) => {
|
||||
@@ -11,6 +13,14 @@ export const AppContext = (props) => {
|
||||
const [isDocSearchModalOpen, setIsDocSearchModalOpen] = useState(false);
|
||||
const [leftSideBarOpenByClick, setLeftSideBarOpenByClick] = useState(currentLocation?.includes('/workflows/') ? false : true)
|
||||
const [windowWidth, setWindowWidth] = useState(serverside === true ? 100 : window.innerWidth);
|
||||
const [brandColor, setBrandColor] = useState(() => localStorage.getItem("brandColor") || "#ff8544");
|
||||
const [brandName, setBrandName] = useState(()=> localStorage.getItem("brandName") || "Shuffle");
|
||||
|
||||
const [themeMode, setThemeMode] = useState(
|
||||
() => localStorage.getItem("theme") || "dark"
|
||||
);
|
||||
const [supportEmail, setSupportEmail] = useState("support@shuffler.io");
|
||||
const [logoutUrl, setLogoutUrl] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (currentLocation?.includes('/workflows/') && leftSideBarOpenByClick === true) {
|
||||
@@ -35,6 +45,57 @@ export const AppContext = (props) => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleThemeChange = (theme) => {
|
||||
if (!theme || theme === "null" || theme === "undefined") {
|
||||
localStorage.setItem("theme", "dark");
|
||||
setThemeMode("dark");
|
||||
return;
|
||||
}
|
||||
|
||||
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
|
||||
const applySystemTheme = () => {
|
||||
const isDark = darkMediaQuery.matches;
|
||||
setThemeMode(isDark ? "dark" : "light");
|
||||
localStorage.setItem("theme", isDark ? "dark" : "light");
|
||||
};
|
||||
|
||||
if (theme === "system") {
|
||||
applySystemTheme();
|
||||
darkMediaQuery.addEventListener("change", applySystemTheme);
|
||||
return () => {
|
||||
darkMediaQuery.removeEventListener("change", applySystemTheme);
|
||||
};
|
||||
} else {
|
||||
setThemeMode(theme);
|
||||
localStorage.setItem("theme", theme);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (serverside === true) return;
|
||||
|
||||
const theme = localStorage.getItem("theme");
|
||||
|
||||
if (!theme || theme === "null" || theme === "undefined") {
|
||||
localStorage.setItem("theme", "dark");
|
||||
setThemeMode("dark");
|
||||
return;
|
||||
}
|
||||
|
||||
let cleanup;
|
||||
if (theme === "system") {
|
||||
cleanup = handleThemeChange("system");
|
||||
} else {
|
||||
handleThemeChange(theme);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (cleanup) cleanup();
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<Context.Provider value={{
|
||||
@@ -42,9 +103,20 @@ export const AppContext = (props) => {
|
||||
setIsDocSearchModalOpen,
|
||||
searchBarModalOpen,
|
||||
setSearchBarModalOpen,
|
||||
supportEmail,
|
||||
setSupportEmail,
|
||||
logoutUrl,
|
||||
setLogoutUrl,
|
||||
leftSideBarOpenByClick,
|
||||
setLeftSideBarOpenByClick,
|
||||
windowWidth
|
||||
windowWidth,
|
||||
themeMode,
|
||||
setThemeMode,
|
||||
handleThemeChange,
|
||||
brandColor,
|
||||
setBrandColor,
|
||||
brandName,
|
||||
setBrandName,
|
||||
}}>
|
||||
{props.children}
|
||||
</Context.Provider>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const data = [
|
||||
export default function defaultCytoscapeStyle(theme) {
|
||||
return [
|
||||
{
|
||||
selector: "node",
|
||||
css: {
|
||||
@@ -43,7 +44,7 @@ const data = [
|
||||
"margin-right": "10px",
|
||||
width: "80px",
|
||||
height: "80px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary || "white",
|
||||
padding: "10px",
|
||||
margin: "5px",
|
||||
"border-width": "1px",
|
||||
@@ -59,7 +60,7 @@ const data = [
|
||||
label: "data(label)",
|
||||
"text-margin-y": "-15px",
|
||||
width: "2px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary || "white",
|
||||
"line-fill": "linear-gradient",
|
||||
"line-gradient-stop-positions": ["0.0", "100"],
|
||||
"line-gradient-stop-colors": ["grey", "grey"],
|
||||
@@ -139,7 +140,7 @@ const data = [
|
||||
width: "8px",
|
||||
height: "8px",
|
||||
"border-width": 1,
|
||||
"border-color": "white",
|
||||
"border-color": theme.palette.text.primary || "white",
|
||||
"z-index": 5002,
|
||||
"overlay-opacity": 0,
|
||||
"cursor": "nwse-resize",
|
||||
@@ -190,38 +191,6 @@ const data = [
|
||||
"background-gradient-stop-colors": "data(fillGradient)",
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[app_id="shuffle_agent"]`,
|
||||
css: {
|
||||
"height": "74px",
|
||||
"width": "222px",
|
||||
"background-image": "data(large_image)",
|
||||
"label": function(element) {
|
||||
var elementname = element.data("label")
|
||||
if (elementname === null || elementname === undefined) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if (elementname.length > 15) {
|
||||
elementname = elementname.substring(0, 15) + ".."
|
||||
}
|
||||
|
||||
return elementname
|
||||
},
|
||||
"background-width": "65px",
|
||||
"background-height": "65px",
|
||||
"background-position-x": "20px",
|
||||
//"background-position-x": "center", // Crashes
|
||||
"background-repeat": "no-repeat",
|
||||
|
||||
"font-size": "14px",
|
||||
"text-halign": "center",
|
||||
"text-valign": "center",
|
||||
"text-margin-x": "-140px",
|
||||
"text-margin-y": "0px",
|
||||
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[app_name="Testing"]`,
|
||||
css: {
|
||||
@@ -358,6 +327,43 @@ const data = [
|
||||
"background-height": "100%",
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[app_id="shuffle_agent"]`,
|
||||
css: {
|
||||
"shape": function(element) {
|
||||
return "roundrectangle"
|
||||
},
|
||||
"height": "74px",
|
||||
"width": "222px",
|
||||
"background-image": "data(large_image)",
|
||||
"label": function(element) {
|
||||
var elementname = element.data("label")
|
||||
if (elementname === null || elementname === undefined) {
|
||||
return ""
|
||||
}
|
||||
|
||||
elementname = elementname.replaceAll("_", " ", -1)
|
||||
|
||||
if (elementname.length > 15) {
|
||||
elementname = elementname.substring(0, 15) + ".."
|
||||
}
|
||||
|
||||
return elementname
|
||||
},
|
||||
"background-width": "65px",
|
||||
"background-height": "65px",
|
||||
"background-position-x": "20px",
|
||||
"background-repeat": "no-repeat",
|
||||
"background-opacity": "0.5",
|
||||
|
||||
"font-size": "14px",
|
||||
"text-halign": "center",
|
||||
"text-valign": "center",
|
||||
"text-margin-x": "20px",
|
||||
"text-margin-y": "0px",
|
||||
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "node[!is_valid]",
|
||||
css: {
|
||||
@@ -426,7 +432,7 @@ const data = [
|
||||
{
|
||||
selector: ".executing-highlight",
|
||||
css: {
|
||||
"background-color": "#ffef47",
|
||||
//"background-color": "#ffef47",
|
||||
"border-color": "#ffef47",
|
||||
"border-width": "8px",
|
||||
"transition-property": "border-width",
|
||||
@@ -453,7 +459,7 @@ const data = [
|
||||
"transition-duration": "0.25s",
|
||||
label: "data(label)",
|
||||
"font-size": "18px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary || "white",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -601,7 +607,7 @@ const data = [
|
||||
|
||||
return label
|
||||
},
|
||||
color: "white",
|
||||
color: theme.palette.text.primary || "white",
|
||||
"border-color": "#f85a3e",
|
||||
"background-color": "#1f1f1f",
|
||||
"font-size": "19px",
|
||||
@@ -614,6 +620,7 @@ const data = [
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
//{
|
||||
// selector: 'edge[?hasErrors]',
|
||||
@@ -626,5 +633,3 @@ const data = [
|
||||
// "line-gradient-stop-colors": ["#991818", "#991818"],
|
||||
// },
|
||||
//},
|
||||
|
||||
export default data;
|
||||
|
||||
+295
-1
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { createTheme, adaptV4Theme } from "@mui/material/styles";
|
||||
|
||||
const theme = createTheme(adaptV4Theme({
|
||||
@@ -153,3 +152,298 @@ const theme = createTheme(adaptV4Theme({
|
||||
}));
|
||||
|
||||
export default theme;
|
||||
|
||||
export const getTheme = (themeMode, brandColor) =>
|
||||
createTheme({
|
||||
palette: {
|
||||
mode: themeMode,
|
||||
main: brandColor || "#FF8544",
|
||||
primary: {
|
||||
main: brandColor || "#FF8544",
|
||||
contrastText: "#ffffff",
|
||||
},
|
||||
secondary: {
|
||||
main: "rgba(255,255,255,0.7)",
|
||||
contrastText:"#000000",
|
||||
},
|
||||
text: {
|
||||
primary: themeMode === "dark" ? "#ffffff" : "#1A1A1A",
|
||||
secondary: themeMode === "dark" ? "#9E9E9E" : "#616161",
|
||||
},
|
||||
type: themeMode,
|
||||
inputColor: themeMode === "dark" ? "rgba(39,41,45,1)" : "rgba(245, 245, 245, 1)",
|
||||
textColor: themeMode === "dark" ? "#F1F1F1" : "#1A1A1A",
|
||||
textPrimary: themeMode === "dark" ? "rgba(255, 255, 255, 0.8)" : "rgba(26, 26, 26, 0.8)",
|
||||
surfaceColor: themeMode === "dark" ? "#27292d" : "#EFEFEF",
|
||||
platformColor: themeMode === "dark" ? "#212121" : "#ffffff",
|
||||
backgroundColor: themeMode === "dark" ? "#1a1a1a" : "#f1f1f1",
|
||||
distributionColor: themeMode === "dark" ? "#40E0D0" : "#008080",
|
||||
cardBackgroundColor: themeMode === "dark" ? "#1e1e1e" : "#eaeaea",
|
||||
cardHoverColor: themeMode === "dark" ? "#323232" : "#F0F0F0",
|
||||
hoverColor: themeMode === "dark" ? "#323232" : "#D6D6D6",
|
||||
green: themeMode === "dark" ? "#5cc879" : "#008000",
|
||||
defaultBorder: themeMode === "dark" ? '1px solid #494949' : '1px solid #CCCCCC',
|
||||
linkColor: brandColor === "#ff8544" ? "#f86a3e" : brandColor,
|
||||
|
||||
borderRadius: 10,
|
||||
loaderColor: themeMode === "dark" ? "#1a1a1a" : "#E0E0E0",
|
||||
jsonIconStyle: "round",
|
||||
jsonTheme: themeMode === "dark" ? "summerfruit" : {
|
||||
base00: "#ffffff", // background
|
||||
base01: "#f0f0f0", // very light grey
|
||||
base02: "#f5f5f5", // light grey
|
||||
base03: "#999999", // dim text
|
||||
base04: "#444444", // bold keys
|
||||
base05: "#333333", // normal text
|
||||
base06: "#1a1a1a", // darker text
|
||||
base07: "#000000", // black
|
||||
base08: "#f14c4c", // red
|
||||
base09: "#f58c1f", // orange
|
||||
base0A: "#f2c032", // yellow
|
||||
base0B: "#51975d", // green
|
||||
base0C: "#2aa198", // teal
|
||||
base0D: "#007acc", // blue (keys!)
|
||||
base0E: "#c586c0", // purple
|
||||
base0F: "#d16969", // brown
|
||||
},
|
||||
jsonCollapseStringsAfterLength: 100,
|
||||
drawer: {
|
||||
backgroundColor: themeMode === "dark" ? "#262626" : "#f9f9f9"
|
||||
},
|
||||
reactJsonStyle: {
|
||||
padding: 5,
|
||||
width: "98%",
|
||||
borderRadius: 5,
|
||||
border: themeMode === "dark" ? "1px solid rgba(255,255,255,0.7)" : "1px solid rgba(0,0,0,0.3)",
|
||||
backgroundColor: themeMode === "dark"
|
||||
? "#1A1A1A"
|
||||
: "#f1f1f1",
|
||||
color: themeMode === "dark"
|
||||
? "#F1F1F1"
|
||||
: "#1A1A1A",
|
||||
overflowX: "auto",
|
||||
},
|
||||
textFieldStyle: {
|
||||
backgroundColor: themeMode === "dark" ? "#212121" : "#FFFFFF",
|
||||
color: themeMode === "dark" ? "#ffffff" : "#000000",
|
||||
borderRadius: "5px",
|
||||
height: 40,
|
||||
border: themeMode === "dark" ? "1px solid #4D4D4D" : "1px solid #E0E0E0",
|
||||
},
|
||||
DialogStyle: {
|
||||
backgroundColor: themeMode === "dark" ? "#212121" : "#ffffff",
|
||||
borderRadius: 2,
|
||||
boxShadow: themeMode === "dark" ? "0px 0px 10px 0px rgba(0,0,0,0.75)" : "0px 0px 10px 0px rgba(0,0,0,0.2)",
|
||||
border: themeMode === "dark" ? "1px solid #494949" : "1px solid #cccccc",
|
||||
},
|
||||
innerTextfieldStyle: {
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
backgroundColor: themeMode === "dark" ? "#212121" : "#f5f5f5",
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: themeMode === "dark" ? "#212121" : "#ffffff",
|
||||
color: themeMode === "dark" ? "#ffffff" : "#000000",
|
||||
border: themeMode === "dark" ? "1px solid #494949" : "1px solid #cccccc",
|
||||
},
|
||||
chipStyle: {
|
||||
backgroundColor: themeMode === "dark" ? "#333333" : "#F5F5F5",
|
||||
borderColor: themeMode === "dark" ? "#444444" : "#E0E0E0",
|
||||
color: themeMode === "dark" ? "#FFFFFF" : "#333333",
|
||||
},
|
||||
defaultImage: "/images/no_image.png",
|
||||
singulOrange: "/images/singul_orange.png",
|
||||
singulGreen: "/images/singul_green.png",
|
||||
singulBlackWhite: "/images/singul_black_white.png",
|
||||
scrollbarColor: themeMode === "dark" ? "#494949 #2f2f2f": "#c1c1c1 #f1f1f1",
|
||||
scrollbarColorTransparent: themeMode === "dark" ? '#494949 transparent': "#c1c1c1 transparent",
|
||||
},
|
||||
typography: {
|
||||
fontFamily: `"inter", "Roboto", "Helvetica", "Arial", sans-serif`,
|
||||
color: themeMode === "dark" ? "#ffffff" : "#000000",
|
||||
useNextVariants: true,
|
||||
fontWeightLight: 300,
|
||||
fontWeightRegular: 400,
|
||||
fontWeightMedium: 500,
|
||||
fontWeightSemiBold: 600,
|
||||
fontWeightBold: 700,
|
||||
allVariants: {
|
||||
color: themeMode === "dark" ? "#ffffff" : "#1A1A1A",
|
||||
},
|
||||
h1: {
|
||||
fontSize: 40,
|
||||
color: themeMode === "dark" ? "#ffffff" : "#1A1A1A"
|
||||
},
|
||||
h2: {
|
||||
fontSize: 36,
|
||||
color: themeMode === "dark" ? "#ffffff" : "#1A1A1A"
|
||||
},
|
||||
h3: {
|
||||
fontSize: 32,
|
||||
color: themeMode === "dark" ? "#ffffff" : "#1A1A1A"
|
||||
},
|
||||
h4: {
|
||||
fontSize: 30,
|
||||
fontWeight: 500,
|
||||
color: themeMode === "dark" ? "#ffffff" : "#1A1A1A"
|
||||
},
|
||||
h6: {
|
||||
fontSize: 22,
|
||||
color: themeMode === "dark" ? "#ffffff" : "#1A1A1A"
|
||||
},
|
||||
body1: {
|
||||
fontSize: 16,
|
||||
color: themeMode === "dark" ? "#ffffff" : "#1A1A1A"
|
||||
},
|
||||
body2: {
|
||||
fontSize: 14,
|
||||
color: themeMode === "dark" ? "#ffffff" : "#1A1A1A"
|
||||
},
|
||||
},
|
||||
components: {
|
||||
MuiButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
textTransform: 'none',
|
||||
borderRadius: '4px',
|
||||
},
|
||||
},
|
||||
variants: [
|
||||
{
|
||||
props: { variant: 'text', color: 'primary' },
|
||||
style: {
|
||||
color: themeMode === "dark" ? "#ffffff" : "#1A1A1A",
|
||||
whiteSpace: "nowrap",
|
||||
textWrap: "normal",
|
||||
},
|
||||
},
|
||||
{
|
||||
props: { variant: 'text', color: 'secondary' },
|
||||
style: {
|
||||
color: themeMode === "dark" ? "#9E9E9E" : "#616161",
|
||||
whiteSpace: "nowrap",
|
||||
textWrap: "normal",
|
||||
},
|
||||
},
|
||||
{
|
||||
props: { variant: 'contained', color: 'primary' },
|
||||
style: {
|
||||
backgroundColor: themeMode === "dark" ? brandColor || '#ff8544' : brandColor || '#FF7C35',
|
||||
color: themeMode === "dark" ? '#1a1a1a': '#FFFFFF',
|
||||
borderRadius: '4px',
|
||||
whiteSpace: "nowrap",
|
||||
textWrap: "normal",
|
||||
'&:hover': {
|
||||
fontWeight: 600,
|
||||
backgroundColor: themeMode === 'dark' ? brandColor || "#ff955c" : brandColor || '#FF8D4F',
|
||||
color: themeMode === "dark" ? '#1a1a1a': '#FFFFFF',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
props: { variant: 'contained', color: 'secondary' },
|
||||
style: {
|
||||
backgroundColor: themeMode === "dark" ? '#494949' : '#C9C9C9',
|
||||
color: themeMode === "dark" ? '#ffffff' : '#4C4C4C',
|
||||
borderRadius: '4px',
|
||||
boxShadow: 'none',
|
||||
whiteSpace: "nowrap",
|
||||
textWrap: "normal",
|
||||
'&:hover': {
|
||||
fontWeight: 600,
|
||||
border: themeMode === "dark" ? '1px solid #f1f1f1' : 'none',
|
||||
backgroundColor: themeMode === "dark" ? '#494949' : '#C9C9C9',
|
||||
color: themeMode === "dark" ? '#ffffff' : '#4C4C4C',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
props: { variant: 'outlined', color: 'primary' },
|
||||
style: {
|
||||
borderColor: themeMode === "dark" ? brandColor || "#ff8544" : brandColor || "#cc5f1f",
|
||||
color: themeMode === "dark" ? brandColor || "#ff8544" : brandColor || "#cc5f1f",
|
||||
whiteSpace: "nowrap",
|
||||
fontWeight: 'normal',
|
||||
textWrap: "normal",
|
||||
'&:hover': {
|
||||
backgroundColor: themeMode === "dark" ? brandColor || "#ff8544" : "#ffe8dc",
|
||||
color: themeMode === "dark" ? "#1a1a1a" : "#8a3d00",
|
||||
fontWeight: 600,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
props: { variant: 'outlined', color: 'secondary' },
|
||||
style: {
|
||||
border: '1px solid #C5C5C5',
|
||||
color: themeMode === "dark" ? '#C5C5C5' : '#2D2D2D',
|
||||
whiteSpace: "nowrap",
|
||||
textWrap: "normal",
|
||||
'&:hover': {
|
||||
backgroundColor: themeMode === "dark" ? '#C5C5C5' : '#EFEFEF',
|
||||
borderColor: themeMode === "dark" ? '#C5C5C5' : '#2D2D2D',
|
||||
fontWeight: 600,
|
||||
color: themeMode === "dark" ? '#1a1a1a' : '#1A1A1A',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
MuiTab: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: themeMode === "dark" ? "#C5C5C5" : "#1A1A1A",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
overrides: {
|
||||
MuiMenu: {
|
||||
list: {
|
||||
backgroundColor: themeMode === "dark" ? "#27292d" : "#ffffff",
|
||||
},
|
||||
},
|
||||
MuiCssBaseline: {
|
||||
MuiCssBaseline: {
|
||||
styleOverrides: `
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 300;
|
||||
src: local('Roboto Light'), local('Roboto-Light');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 600;
|
||||
src: local('Roboto SemiBold'), local('Roboto-SemiBold');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold');
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import AdminNavBar from '../components/AdminNavBar.jsx';
|
||||
import { toast } from "react-toastify";
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
|
||||
const Admin2 = (props) => {
|
||||
// Destructure props if needed
|
||||
@@ -10,13 +11,15 @@ const Admin2 = (props) => {
|
||||
const [selectedOrganization, setSelectedOrganization] = useState({});
|
||||
const [organizationFeatures, setOrganizationFeatures] = useState({});
|
||||
const [orgRequest, setOrgRequest] = React.useState(true);
|
||||
const [isOrgLoaded, setIsOrgLoaded] = React.useState(false);
|
||||
const {brandName} = useContext(Context)
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||
|
||||
if (document !== undefined) {
|
||||
if (selectedOrganization?.name !== undefined) {
|
||||
document.title = selectedOrganization?.name + " - Admin - Shuffle"
|
||||
document.title = brandName?.length > 0 ? selectedOrganization?.name + ` - Admin - ${brandName}` : selectedOrganization?.name + ` - Admin - Shuffle`;
|
||||
} else {
|
||||
document.title = "Admin - Shuffle"
|
||||
document.title = brandName?.length > 0 ? `Admin - ${brandName}` : `Admin - Shuffle`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +154,8 @@ const Admin2 = (props) => {
|
||||
.catch((error) => {
|
||||
console.log("Error getting org: ", error);
|
||||
toast("Error getting current organization");
|
||||
}).finally(() => {
|
||||
setIsOrgLoaded(true)
|
||||
});
|
||||
};
|
||||
|
||||
@@ -330,7 +335,7 @@ const Admin2 = (props) => {
|
||||
|
||||
return (
|
||||
<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}/>
|
||||
<AdminNavBar userdata={userdata} isLoaded={isLoaded} isOrgLoaded={isOrgLoaded} 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}/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -59,6 +59,7 @@ const ApiExplorer = React.lazy(() => import("../components/ApiExplorer.jsx"));
|
||||
|
||||
const ApiExplorerWrapper = (props) => {
|
||||
const { globalUrl, serverside, userdata, isLoggedIn, isLoaded} = props;
|
||||
const { supportEmail } = useContext(Context);
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
@@ -165,7 +166,7 @@ const ApiExplorerWrapper = (props) => {
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
toast.error(`Failed to get API data for '${appname}' (1). Contact support@shuffler.io if this persists.`, {
|
||||
toast.error(`Failed to get API data for '${appname}' (1). Contact ${supportEmail} if this persists.`, {
|
||||
"autoClose": 10000,
|
||||
})
|
||||
|
||||
@@ -174,7 +175,7 @@ const ApiExplorerWrapper = (props) => {
|
||||
},3000)
|
||||
}
|
||||
} else {
|
||||
toast.error(`Failed to get API data for '${appname}' (2). Contact support@shuffler.io if this persists.`, {
|
||||
toast.error(`Failed to get API data for '${appname}' (2). Contact ${supportEmail} if this persists.`, {
|
||||
"autoClose": 10000,
|
||||
})
|
||||
setTimeout(()=>{
|
||||
@@ -539,7 +540,7 @@ const ApiExplorerWrapper = (props) => {
|
||||
}else if (openapi?.id?.length > 0) {
|
||||
appid = openapi?.id;
|
||||
}else{
|
||||
toast.error("App id is missing and we can't run the API. Please contact support@shuffler.io if this persists.");
|
||||
toast.error(`App id is missing and we can't run the API. Please contact ${supportEmail} if this persists.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -673,7 +674,7 @@ const ApiExplorerWrapper = (props) => {
|
||||
|
||||
if (data.result.includes("custom_action doesn't exist")) {
|
||||
// No timeout error
|
||||
toast.info("This API is being rebuilt due to missing functionality. Please wait a minute or two, then try again. If this persists, please report to support@shuffler.io", {
|
||||
toast.info(`This API is being rebuilt due to missing functionality. Please wait a minute or two, then try again. If this persists, please report to ${supportEmail}`, {
|
||||
"autoClose": 90000,
|
||||
})
|
||||
} else if (data.result.includes("authentication") && data.result.includes("Oauth2")) {
|
||||
|
||||
+170
-142
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { BrowserView, MobileView } from "react-device-detect";
|
||||
import theme from '../theme.jsx';
|
||||
import { getTheme } from '../theme.jsx';
|
||||
|
||||
import {
|
||||
Paper,
|
||||
@@ -57,6 +57,7 @@ import { ToastContainer, toast } from "react-toastify"
|
||||
import words from "shellwords";
|
||||
|
||||
import AvatarEditor from "react-avatar-editor";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
const surfaceColor = "#27292D";
|
||||
const inputColor = "#383B40";
|
||||
@@ -67,33 +68,7 @@ const bodyDivStyle = {
|
||||
zoom: 0.8,
|
||||
};
|
||||
|
||||
const actionListStyle = {
|
||||
paddingLeft: "10px",
|
||||
paddingRight: "10px",
|
||||
paddingBottom: "10px",
|
||||
paddingTop: "10px",
|
||||
marginTop: "5px",
|
||||
display: "flex",
|
||||
color: "white",
|
||||
position: "relative",
|
||||
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
};
|
||||
|
||||
const boxStyle = {
|
||||
color: "white",
|
||||
flex: "1",
|
||||
marginLeft: "10px",
|
||||
marginRight: "10px",
|
||||
paddingLeft: "30px",
|
||||
paddingRight: "30px",
|
||||
paddingBottom: "30px",
|
||||
paddingTop: "30px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
};
|
||||
|
||||
const dividerStyle = {
|
||||
marginBottom: "10px",
|
||||
@@ -427,9 +402,40 @@ const AppCreator = (defaultprops) => {
|
||||
const [actionAmount, setActionAmount] = useState(increaseAmount);
|
||||
const [newAppGroup, setNewAppGroup] = useState("")
|
||||
|
||||
const { themeMode, supportEmail, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
const [oauth2Scopes, setOauth2Scopes] = useState([]);
|
||||
const [oauth2Type, setOauth2Type] = useState("delegated");
|
||||
|
||||
const actionListStyle = {
|
||||
paddingLeft: "10px",
|
||||
paddingRight: "10px",
|
||||
paddingBottom: "10px",
|
||||
paddingTop: "10px",
|
||||
marginTop: "5px",
|
||||
display: "flex",
|
||||
color: theme.palette.text.primary,
|
||||
position: "relative",
|
||||
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
};
|
||||
|
||||
const boxStyle = {
|
||||
color: theme.palette.text.primary,
|
||||
flex: "1",
|
||||
marginLeft: "10px",
|
||||
marginRight: "10px",
|
||||
paddingLeft: "30px",
|
||||
paddingRight: "30px",
|
||||
paddingBottom: "30px",
|
||||
paddingTop: "30px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
};
|
||||
|
||||
//client_credentials
|
||||
const [oauth2GrantType, setOauth2GrantType] = useState("");
|
||||
const defaultAuth = {
|
||||
@@ -2626,7 +2632,7 @@ const AppCreator = (defaultprops) => {
|
||||
if (response.status === 403) {
|
||||
var urlParams = new URLSearchParams(window.location.search)
|
||||
if (urlParams.has("id")) {
|
||||
toast.error("Please log in to build this app. If this error persists, please contact support@shuffler.io")
|
||||
toast.error(`Please log in to build this app. If this error persists, please contact ${supportEmail}`)
|
||||
} else {
|
||||
toast.error("Failed to save the app as you are not the owner. Redirecting you to the forking page. When there, save again.")
|
||||
if (props.match.params.appid !== undefined && props.match.params.appid !== null && props.match.params.appid.length > 0) {
|
||||
@@ -2678,12 +2684,12 @@ const AppCreator = (defaultprops) => {
|
||||
|
||||
const bearerAuth =
|
||||
authenticationOption === "Bearer auth" ? (
|
||||
<div style={{ color: "white" }}>
|
||||
<div style={{ color: theme.palette.text.primary }}>
|
||||
<h4>
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://swagger.io/docs/specification/authentication/bearer-authentication/"
|
||||
style={{ textDecoriation: "none", color: "#f85a3e" }}
|
||||
style={{ textDecoriation: "none", color: theme.palette.linkColor }}
|
||||
>
|
||||
Bearer auth
|
||||
</a>
|
||||
@@ -2696,12 +2702,12 @@ const AppCreator = (defaultprops) => {
|
||||
// Basicauth
|
||||
const basicAuth =
|
||||
authenticationOption === "Basic auth" ? (
|
||||
<div style={{ color: "white" }}>
|
||||
<div style={{ color: theme.palette.text.primary }}>
|
||||
<h4>
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://swagger.io/docs/specification/authentication/basic-authentication/"
|
||||
style={{ textDecoriation: "none", color: "#f85a3e" }}
|
||||
style={{ textDecoriation: "none", color: theme.palette.linkColor }}
|
||||
>
|
||||
Basic authentication
|
||||
</a>
|
||||
@@ -2795,7 +2801,7 @@ const AppCreator = (defaultprops) => {
|
||||
flex: 2,
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
marginRight: 5,
|
||||
}}
|
||||
fullWidth={true}
|
||||
@@ -2813,7 +2819,8 @@ const AppCreator = (defaultprops) => {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
minHeight: 50,
|
||||
marginLeft: 5,
|
||||
maxWidth: "95%",
|
||||
@@ -2828,7 +2835,7 @@ const AppCreator = (defaultprops) => {
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
flex: 2,
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
marginRight: 5,
|
||||
}}
|
||||
fullWidth={true}
|
||||
@@ -2843,7 +2850,8 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
minHeight: 50,
|
||||
marginLeft: 5,
|
||||
maxWidth: "95%",
|
||||
@@ -2861,9 +2869,9 @@ const AppCreator = (defaultprops) => {
|
||||
value={extraAuth[index].type}
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
paddingLeft: "10px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
height: 50,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
}}
|
||||
@@ -2874,14 +2882,14 @@ const AppCreator = (defaultprops) => {
|
||||
>
|
||||
<MenuItem
|
||||
key={index}
|
||||
style={{ backgroundColor: inputColor, color: "white" }}
|
||||
style={{ backgroundColor: theme.palette.backgroundColor, color: theme.palette.text.primary }}
|
||||
value={"header"}
|
||||
>
|
||||
Header
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
key={index}
|
||||
style={{ backgroundColor: inputColor, color: "white" }}
|
||||
style={{ backgroundColor: theme.palette.backgroundColor, color: theme.palette.text.primary }}
|
||||
value={"query"}
|
||||
>
|
||||
Query
|
||||
@@ -2929,7 +2937,7 @@ const AppCreator = (defaultprops) => {
|
||||
|
||||
const jwtAuth =
|
||||
authenticationOption === "JWT" ? (
|
||||
<div style={{ color: "white", marginTop: 20 }}>
|
||||
<div style={{ color: theme.palette.text.primary, marginTop: 20 }}>
|
||||
<Typography variant="body1">JWT authentication</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
@@ -2948,7 +2956,7 @@ const AppCreator = (defaultprops) => {
|
||||
variant="outlined"
|
||||
defaultValue={parameterName}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
Must start with / and be a valid path
|
||||
</span>
|
||||
}
|
||||
@@ -2958,7 +2966,7 @@ const AppCreator = (defaultprops) => {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -2979,7 +2987,7 @@ const AppCreator = (defaultprops) => {
|
||||
variant="outlined"
|
||||
defaultValue={parameterName}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
Must use 'key=value&key=value' format
|
||||
</span>
|
||||
}
|
||||
@@ -2991,7 +2999,7 @@ const AppCreator = (defaultprops) => {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3001,7 +3009,7 @@ const AppCreator = (defaultprops) => {
|
||||
|
||||
const oauth2Auth =
|
||||
authenticationOption === "Oauth2" ? (
|
||||
<div style={{ color: "white", marginTop: 20 }}>
|
||||
<div style={{ color: theme.palette.text.primary, marginTop: 20 }}>
|
||||
<Typography variant="body1">Oauth2 authentication</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
@@ -3060,7 +3068,7 @@ const AppCreator = (defaultprops) => {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3111,7 +3119,7 @@ const AppCreator = (defaultprops) => {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3160,7 +3168,7 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3177,7 +3185,7 @@ const AppCreator = (defaultprops) => {
|
||||
required
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
maxHeight: 160,
|
||||
},
|
||||
}}
|
||||
@@ -3202,7 +3210,7 @@ const AppCreator = (defaultprops) => {
|
||||
|
||||
const apiKey =
|
||||
authenticationOption === "API key" ? (
|
||||
<div style={{ color: "white", marginTop: 20 }}>
|
||||
<div style={{ color: theme.palette.text.primary, marginTop: 20 }}>
|
||||
<Typography variant="body1">API key authentication</Typography>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
<b>Do NOT put your actual API-key.</b> Add the name of the field used for authentication, e.g. "X-APIKEY".
|
||||
@@ -3221,7 +3229,7 @@ const AppCreator = (defaultprops) => {
|
||||
variant="outlined"
|
||||
value={parameterName}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
Can't be empty or contain any of the following: !#$%&'^"+-._~|]+$:=
|
||||
</span>
|
||||
}
|
||||
@@ -3238,7 +3246,7 @@ const AppCreator = (defaultprops) => {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3255,7 +3263,7 @@ const AppCreator = (defaultprops) => {
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
backgroundColor: inputColor,
|
||||
paddingLeft: 10,
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
height: 57,
|
||||
}}
|
||||
inputProps={{
|
||||
@@ -3271,7 +3279,7 @@ const AppCreator = (defaultprops) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={index}
|
||||
style={{ backgroundColor: inputColor, color: "white" }}
|
||||
style={{ backgroundColor: inputColor, color: theme.palette.text.primary }}
|
||||
value={data}
|
||||
>
|
||||
{data}
|
||||
@@ -3463,15 +3471,14 @@ const AppCreator = (defaultprops) => {
|
||||
<Tooltip title={chipRequired ? "Make not required" : "Make required"}>
|
||||
<Chip
|
||||
style={{
|
||||
backgroundColor: chipRequired ? "#f86a3e" : "#3d3f43",
|
||||
backgroundColor: chipRequired ? "#f86a3e" : theme.palette.chipStyle.backgroundColor,
|
||||
height: 30,
|
||||
margin: 3,
|
||||
paddingLeft: 5,
|
||||
paddingRight: 5,
|
||||
height: 28,
|
||||
cursor: "pointer",
|
||||
borderColor: "#3d3f43",
|
||||
color: "white",
|
||||
borderColor: theme.palette.chipStyle.borderColor,
|
||||
color: theme.palette.chipStyle.color,
|
||||
}}
|
||||
label={parsedChip}
|
||||
onClick={() => {
|
||||
@@ -3557,7 +3564,7 @@ const AppCreator = (defaultprops) => {
|
||||
placeholder={"Query name (key)"}
|
||||
label={"Query Key"}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
Click required to flip
|
||||
</span>
|
||||
}
|
||||
@@ -3569,7 +3576,7 @@ const AppCreator = (defaultprops) => {
|
||||
style={{flex: 3}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3589,7 +3596,7 @@ const AppCreator = (defaultprops) => {
|
||||
style={{flex: 2}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3662,7 +3669,7 @@ const AppCreator = (defaultprops) => {
|
||||
)}
|
||||
<TextField
|
||||
required
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: inputColor }}
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.textFieldStyle.backgroundColor }}
|
||||
fullWidth={true}
|
||||
placeholder={
|
||||
'{\n\t"example": "${example}",\n\t"apikey": "${apikey}",\n\t"search": "1.2.3.5"\n}'
|
||||
@@ -3678,7 +3685,7 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
key={currentAction}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
Shows an example body to the user. ${} creates variables.
|
||||
</span>
|
||||
}
|
||||
@@ -3687,7 +3694,8 @@ const AppCreator = (defaultprops) => {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3700,7 +3708,7 @@ const AppCreator = (defaultprops) => {
|
||||
<b>Example success response</b>
|
||||
<TextField
|
||||
required
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: inputColor }}
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.textFieldStyle.backgroundColor }}
|
||||
fullWidth={true}
|
||||
placeholder={
|
||||
'{\n\t"email": "testing@test.com",\n\t"firstname": "testing"\n}'
|
||||
@@ -3712,14 +3720,15 @@ const AppCreator = (defaultprops) => {
|
||||
defaultValue={currentAction["example_response"]}
|
||||
onChange={(e) => setActionField("example_response", e.target.value)}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
Helps with autocompletion and understanding of the endpoint
|
||||
</span>
|
||||
}
|
||||
key={currentAction}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3794,8 +3803,8 @@ const AppCreator = (defaultprops) => {
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: surfaceColor,
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.drawer.backgroundColor,
|
||||
color: theme.palette.text.primary,
|
||||
minWidth: 700,
|
||||
maxWidth: 700,
|
||||
},
|
||||
@@ -3812,15 +3821,15 @@ const AppCreator = (defaultprops) => {
|
||||
setFileUploadEnabled(false);
|
||||
}}
|
||||
>
|
||||
<FormControl style={{ backgroundColor: surfaceColor, color: "white" }}>
|
||||
<FormControl style={{ backgroundColor: theme.palette.drawer.backgroundColor, color: theme.palette.text.primary }}>
|
||||
<DialogTitle style={{marginTop: 45, }}>
|
||||
<div style={{ color: "white" }}>New action</div>
|
||||
<div style={{ color: theme.palette.text.primary }}>New action</div>
|
||||
</DialogTitle>
|
||||
<DialogContent style={{paddingBottom: 100, }}>
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://shuffler.io/docs/app_creation#actions"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
style={{ textDecoration: "none", color: theme.palette.linkColor }}
|
||||
>
|
||||
Learn more about actions
|
||||
</a>
|
||||
@@ -3832,7 +3841,8 @@ const AppCreator = (defaultprops) => {
|
||||
flex: "1",
|
||||
marginTop: 5,
|
||||
marginRight: 15,
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
}}
|
||||
fullWidth={true}
|
||||
placeholder="Name"
|
||||
@@ -3871,7 +3881,8 @@ const AppCreator = (defaultprops) => {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3883,7 +3894,8 @@ const AppCreator = (defaultprops) => {
|
||||
flex: "1",
|
||||
marginTop: 5,
|
||||
marginRight: "15px",
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
}}
|
||||
fullWidth={true}
|
||||
placeholder="Description"
|
||||
@@ -3895,7 +3907,8 @@ const AppCreator = (defaultprops) => {
|
||||
onChange={(e) => setActionField("description", e.target.value)}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -3917,14 +3930,18 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
value={currentActionMethod}
|
||||
style={{
|
||||
backgroundColor: inputColor,
|
||||
paddingLeft: "10px",
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
height: "50px",
|
||||
}}
|
||||
inputProps={{
|
||||
name: "Method",
|
||||
id: "method-option",
|
||||
style: {
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -3939,7 +3956,7 @@ const AppCreator = (defaultprops) => {
|
||||
>
|
||||
<Chip
|
||||
style={{
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
minWidth: 80,
|
||||
marginRight: 10,
|
||||
@@ -3963,7 +3980,8 @@ const AppCreator = (defaultprops) => {
|
||||
flex: "1",
|
||||
marginRight: "15px",
|
||||
marginTop: "5px",
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
}}
|
||||
fullWidth={true}
|
||||
placeholder="URL path"
|
||||
@@ -3976,7 +3994,7 @@ const AppCreator = (defaultprops) => {
|
||||
setUrlPath(e.target.value);
|
||||
}}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
The path to use. Must start with /. Use {"{variablename}"} to
|
||||
have path variables
|
||||
</span>
|
||||
@@ -3987,7 +4005,8 @@ const AppCreator = (defaultprops) => {
|
||||
input: classes.input,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
}}
|
||||
onBlur={(event) => {
|
||||
@@ -4270,7 +4289,7 @@ const AppCreator = (defaultprops) => {
|
||||
defaultValue={currentAction["file_field"]}
|
||||
onChange={(e) => setActionField("file_field", e.target.value)}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
The File field to interact with
|
||||
</span>
|
||||
}
|
||||
@@ -4279,7 +4298,7 @@ const AppCreator = (defaultprops) => {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -4294,7 +4313,8 @@ const AppCreator = (defaultprops) => {
|
||||
flex: "1",
|
||||
marginRight: "15px",
|
||||
marginTop: "5px",
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
}}
|
||||
fullWidth={true}
|
||||
placeholder={
|
||||
@@ -4308,13 +4328,14 @@ const AppCreator = (defaultprops) => {
|
||||
minRows="2"
|
||||
onChange={(e) => setActionField("headers", e.target.value)}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
Headers that are part of the request. Default: EMPTY
|
||||
</span>
|
||||
}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -4323,14 +4344,14 @@ const AppCreator = (defaultprops) => {
|
||||
{bodyInfo}
|
||||
<Divider
|
||||
style={{
|
||||
backgroundColor: "rgba(255,255,255,0.5)",
|
||||
backgroundColor: theme.palette.defaultBorder,
|
||||
marginTop: 15,
|
||||
marginBottom: 15,
|
||||
}}
|
||||
/>
|
||||
{exampleResponse}
|
||||
</DialogContent>
|
||||
<div style={{position: "fixed", backgroundColor: theme.palette.surfaceColor, bottom: 0, width: "100%", padding: 25, borderTop: "1px solid rgba(255,255,255,0.3)", }}>
|
||||
<div style={{position: "fixed", backgroundColor: theme.palette.drawer.backgroundColor, bottom: 0, width: "100%", padding: 25, borderTop: theme.palette.defaultBorder, }}>
|
||||
<Button
|
||||
color="primary"
|
||||
variant={urlPath.length > 0 ? "contained" : "outlined"}
|
||||
@@ -4449,7 +4470,7 @@ const AppCreator = (defaultprops) => {
|
||||
<Chip
|
||||
style={{
|
||||
backgroundColor: bgColor,
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
minWidth: 80,
|
||||
marginRight: 10,
|
||||
@@ -4501,9 +4522,9 @@ const AppCreator = (defaultprops) => {
|
||||
style={{
|
||||
border: data.action_label === undefined || data.action_label === "No Label" ? "" : `2px solid ${bgColor}`,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
paddingLeft: 10,
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
height: 30,
|
||||
maxWidth: 35,
|
||||
marginLeft: 10,
|
||||
@@ -4620,13 +4641,13 @@ const AppCreator = (defaultprops) => {
|
||||
|
||||
|
||||
const tagView = (
|
||||
<div style={{ color: "white" }}>
|
||||
<div style={{ color: theme.palette.text.primary }}>
|
||||
{/*
|
||||
<ChipInput
|
||||
style={{marginTop: 10}}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
placeholder="Categories"
|
||||
@@ -4661,7 +4682,7 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
value={newWorkflowCategories.length === 0 ? "Select a category" : newWorkflowCategories[0]}
|
||||
|
||||
style={{ backgroundColor: inputColor, color: "white", height: "50px" }}
|
||||
style={{ backgroundColor: theme.palette.backgroundColor, color: theme.palette.text.primary, height: "50px" }}
|
||||
>
|
||||
{categories.map((data, index) => {
|
||||
if (data === undefined || data === null || data === "" || data === undefined || data === null || data === "") {
|
||||
@@ -4671,7 +4692,7 @@ const AppCreator = (defaultprops) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={index}
|
||||
style={{ backgroundColor: inputColor, color: "white" }}
|
||||
sx={{ backgroundColor: theme.palette.backgroundColor, color: theme.palette.text.primary, "&:hover" : { backgroundColor: theme.palette.hoverColor} }}
|
||||
value={data.name}
|
||||
>
|
||||
{data.name}
|
||||
@@ -4701,7 +4722,7 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -4713,7 +4734,7 @@ const AppCreator = (defaultprops) => {
|
||||
style={{ marginTop: 10 }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
placeholder="Tags"
|
||||
@@ -4786,7 +4807,7 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
height: 50,
|
||||
fontSize: "1em",
|
||||
},
|
||||
@@ -5101,7 +5122,7 @@ const AppCreator = (defaultprops) => {
|
||||
|
||||
/*
|
||||
{selectedAction.authentication.map(data => (
|
||||
<MenuItem key={data.id} style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
||||
<MenuItem key={data.id} style={{backgroundColor: inputColor, color: theme.palette.text.primary}} value={data}>
|
||||
*/
|
||||
};
|
||||
|
||||
@@ -5120,7 +5141,7 @@ const AppCreator = (defaultprops) => {
|
||||
target="_blank"
|
||||
rel="norefferer"
|
||||
href="https://shuffler.io/docs/app_creation#authentication"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
style={{ textDecoration: "none", color: theme.palette.linkColor }}
|
||||
>
|
||||
What is this?
|
||||
</a>
|
||||
@@ -5135,7 +5156,7 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
height: 50,
|
||||
@@ -5175,7 +5196,7 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
height: 50,
|
||||
@@ -5225,7 +5246,7 @@ const AppCreator = (defaultprops) => {
|
||||
};
|
||||
|
||||
const actionView = (
|
||||
<div style={{ color: "white", position: "relative" }}>
|
||||
<div style={{ color: theme.palette.text.primary, position: "relative" }}>
|
||||
<div style={{ position: "absolute", right: 0, top: 0 }}>
|
||||
{actionAmount > 0 && actionAmount < filteredActions.length ? (
|
||||
<Button
|
||||
@@ -5277,15 +5298,14 @@ const AppCreator = (defaultprops) => {
|
||||
key={index}
|
||||
style={{
|
||||
backgroundColor:
|
||||
tag === selectedCategory ? "#f86a3e" : "#3d3f43",
|
||||
tag === selectedCategory ? "#f86a3e" : theme.palette.chipStyle.backgroundColor,
|
||||
height: 30,
|
||||
margin: 3,
|
||||
paddingLeft: 5,
|
||||
paddingRight: 5,
|
||||
height: 28,
|
||||
cursor: "pointer",
|
||||
borderColor: "#3d3f43",
|
||||
color: "white",
|
||||
borderColor: theme.palette.chipStyle.borderColor,
|
||||
color: theme.palette.chipStyle.color,
|
||||
}}
|
||||
label={newname}
|
||||
onClick={() => {
|
||||
@@ -5411,13 +5431,13 @@ const AppCreator = (defaultprops) => {
|
||||
);
|
||||
|
||||
const testView = (
|
||||
<div style={{ color: "white" }}>
|
||||
<div style={{ color: theme.palette.text.primary }}>
|
||||
<h2>Test</h2>
|
||||
Test an action to see whether it performs in an expected way.
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://shuffler.io/docs/app_creation#testing"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
style={{ textDecoration: "none", color: theme.palette.linkColor }}
|
||||
>
|
||||
TBD: Click here to learn more about testing
|
||||
</a>
|
||||
@@ -5572,7 +5592,7 @@ const AppCreator = (defaultprops) => {
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: surfaceColor,
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
minWidth: "300px",
|
||||
minHeight: "300px",
|
||||
},
|
||||
@@ -5721,7 +5741,7 @@ const AppCreator = (defaultprops) => {
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: surfaceColor,
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
minWidth: "800px",
|
||||
minHeight: "320px",
|
||||
},
|
||||
@@ -5741,7 +5761,7 @@ const AppCreator = (defaultprops) => {
|
||||
margin="normal"
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
height: "50px",
|
||||
fontSize: "1em",
|
||||
},
|
||||
@@ -5768,7 +5788,7 @@ const AppCreator = (defaultprops) => {
|
||||
setOpenApi(e.target.value);
|
||||
}}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
Must point to a version 2 or 3 OpenAPI specification.
|
||||
</span>
|
||||
}
|
||||
@@ -5832,14 +5852,14 @@ const AppCreator = (defaultprops) => {
|
||||
|
||||
// Random names for type & autoComplete. Didn't research :^)
|
||||
const landingpageDataBrowser = (
|
||||
<div style={{ paddingBottom: 100, color: "white" }}>
|
||||
<div style={{ paddingBottom: 100, color: theme.palette.text.primary, }}>
|
||||
<Breadcrumbs
|
||||
aria-label="breadcrumb"
|
||||
separator="›"
|
||||
style={{ color: "white" }}
|
||||
style={{ color: theme.palette.text.primary }}
|
||||
>
|
||||
<Link to="/apps" style={{ textDecoration: "none", color: "inherit" }}>
|
||||
<h2 style={{ color: "rgba(255,255,255,0.5)" }}>
|
||||
<h2 style={{ color: theme.palette.textColor }}>
|
||||
<AppsIcon style={{ marginRight: 10 }} />
|
||||
Apps
|
||||
</h2>
|
||||
@@ -5860,10 +5880,10 @@ const AppCreator = (defaultprops) => {
|
||||
ref={(ref) => (upload = ref)}
|
||||
onChange={editHeaderImage}
|
||||
/>
|
||||
<Paper style={boxStyle}>
|
||||
<div style={boxStyle}>
|
||||
<div style={{display: "flex", }}>
|
||||
<div style={{flex: 1, }}>
|
||||
<h2 style={{ marginBottom: "10px", color: "white" }}>
|
||||
<h2 style={{ marginBottom: "10px", color: theme.palette.text.primary }}>
|
||||
General information
|
||||
</h2>
|
||||
</div>
|
||||
@@ -5907,13 +5927,13 @@ const AppCreator = (defaultprops) => {
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://shuffler.io/docs/app_creation#app-creator-instructions"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
style={{ textDecoration: "none", color: theme.palette.linkColor }}
|
||||
>
|
||||
Click to learn more about app creation
|
||||
</a>
|
||||
<div
|
||||
style={{
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
flex: "1",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
@@ -5944,7 +5964,7 @@ const AppCreator = (defaultprops) => {
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div style={{ flex: "3", color: "white", marginLeft: 20, }}>
|
||||
<div style={{ flex: "3", color: theme.palette.text.primary, marginLeft: 20, }}>
|
||||
<div style={{ marginTop: "10px" }} />
|
||||
Name
|
||||
<TextField
|
||||
@@ -5953,7 +5973,7 @@ const AppCreator = (defaultprops) => {
|
||||
flex: "1",
|
||||
marginTop: "5px",
|
||||
marginRight: "15px",
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
}}
|
||||
fullWidth={true}
|
||||
placeholder="Name"
|
||||
@@ -5989,7 +6009,8 @@ const AppCreator = (defaultprops) => {
|
||||
color="primary"
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
height: "50px",
|
||||
fontSize: "1em",
|
||||
},
|
||||
@@ -6005,13 +6026,19 @@ const AppCreator = (defaultprops) => {
|
||||
style={{
|
||||
marginTop: 5,
|
||||
marginRight: 15,
|
||||
backgroundColor: inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
maxHeight: 250,
|
||||
overflowY: "auto"
|
||||
}}
|
||||
fullWidth={true}
|
||||
type="name"
|
||||
id="outlined-with-placeholder"
|
||||
inputProps={{
|
||||
style: {
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
}
|
||||
}}
|
||||
margin="normal"
|
||||
multiline
|
||||
variant="outlined"
|
||||
@@ -6033,7 +6060,7 @@ const AppCreator = (defaultprops) => {
|
||||
/>
|
||||
<Typography
|
||||
variant="h6"
|
||||
style={{ marginTop: 10, marginBottom: 10, color: "white" }}
|
||||
style={{ marginTop: 10, marginBottom: 10, color: theme.palette.text.primary }}
|
||||
>
|
||||
API information
|
||||
</Typography>
|
||||
@@ -6042,14 +6069,15 @@ const AppCreator = (defaultprops) => {
|
||||
</Typography>
|
||||
<TextField
|
||||
color="primary"
|
||||
style={{ backgroundColor: inputColor, marginTop: "5px" }}
|
||||
style={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor, marginTop: "5px" }}
|
||||
InputProps={{
|
||||
classes: {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
@@ -6061,7 +6089,7 @@ const AppCreator = (defaultprops) => {
|
||||
variant="outlined"
|
||||
value={baseUrl}
|
||||
helperText={
|
||||
<span style={{ color: "white", marginBottom: "2px" }}>
|
||||
<span style={{ color: theme.palette.text.primary, marginBottom: "2px" }}>
|
||||
Must start with http(s):// and CANT end with /.{" "}
|
||||
</span>
|
||||
}
|
||||
@@ -6098,7 +6126,7 @@ const AppCreator = (defaultprops) => {
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://shuffler.io/docs/app_creation#authentication"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
style={{ textDecoration: "none", color: theme.palette.linkColor }}
|
||||
>
|
||||
Learn more about app authentication
|
||||
</a>
|
||||
@@ -6122,15 +6150,15 @@ const AppCreator = (defaultprops) => {
|
||||
}}
|
||||
value={authenticationOption}
|
||||
style={{
|
||||
backgroundColor: inputColor,
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.text.primary,
|
||||
height: "50px",
|
||||
}}
|
||||
>
|
||||
{authenticationOptions.map((data, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
style={{ backgroundColor: inputColor, color: "white" }}
|
||||
sx={{ backgroundColor: theme.palette.backgroundColor, color: theme.palette.text.primary, "&:hover": {backgroundColor: theme.palette.backgroundColor} }}
|
||||
value={data}
|
||||
>
|
||||
{data}
|
||||
@@ -6165,14 +6193,14 @@ const AppCreator = (defaultprops) => {
|
||||
value={oauth2Type}
|
||||
style={{
|
||||
backgroundColor: inputColor,
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
height: "50px",
|
||||
}}
|
||||
>
|
||||
{["delegated", "application"].map((data, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
style={{ backgroundColor: inputColor, color: "white" }}
|
||||
style={{ backgroundColor: inputColor, color: theme.palette.text.primary }}
|
||||
value={data}
|
||||
>
|
||||
{data}
|
||||
@@ -6193,14 +6221,14 @@ const AppCreator = (defaultprops) => {
|
||||
value={oauth2GrantType}
|
||||
style={{
|
||||
backgroundColor: inputColor,
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
height: "50px",
|
||||
}}
|
||||
>
|
||||
{["client_credentials", "password"].map((data, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
style={{ backgroundColor: inputColor, color: "white" }}
|
||||
style={{ backgroundColor: inputColor, color: theme.palette.text.primary }}
|
||||
value={data}
|
||||
>
|
||||
{data}
|
||||
@@ -6225,8 +6253,8 @@ const AppCreator = (defaultprops) => {
|
||||
|
||||
{/*authenticationOption === "No authentication" ? null :
|
||||
<FormControlLabel
|
||||
style={{color: "white", marginBottom: 0, marginTop: 20}}
|
||||
label=<div style={{color: "white"}}>Authentication required (default true)</div>
|
||||
style={{color: theme.palette.text.primary, marginBottom: 0, marginTop: 20}}
|
||||
label=<div style={{color: theme.palette.text.primary}}>Authentication required (default true)</div>
|
||||
control={<Switch checked={authenticationRequired} onChange={() => {
|
||||
setAuthenticationRequired(!authenticationRequired)
|
||||
}} />}
|
||||
@@ -6321,7 +6349,7 @@ const AppCreator = (defaultprops) => {
|
||||
{errorCode.length > 0 ? `Upload Error: ${errorCode}` : null}
|
||||
</Typography>
|
||||
|
||||
</Paper>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import ReactGA from "react-ga4";
|
||||
import Markdown from "react-markdown";
|
||||
import algoliasearch from "algoliasearch/lite";
|
||||
@@ -86,53 +86,6 @@ import { sortByKey } from "../views/AngularWorkflow.jsx";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import aa from "search-insights";
|
||||
|
||||
const surfaceColor = "#27292D";
|
||||
const inputColor = "#383B40";
|
||||
|
||||
const chipStyle = {
|
||||
marginTop: 5,
|
||||
backgroundColor: "#3d3f43",
|
||||
height: 30,
|
||||
marginRight: 5,
|
||||
paddingLeft: 5,
|
||||
paddingRight: 5,
|
||||
height: 28,
|
||||
cursor: "pointer",
|
||||
borderColor: "#3d3f43",
|
||||
color: "white",
|
||||
};
|
||||
|
||||
const actionListStyle = {
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingTop: 10,
|
||||
marginTop: 5,
|
||||
backgroundColor: inputColor,
|
||||
display: "flex",
|
||||
color: "white",
|
||||
maxWidth: 350,
|
||||
minWidth: 350,
|
||||
maxHeight: 54,
|
||||
overflow: "hidden",
|
||||
};
|
||||
|
||||
const boxStyle = {
|
||||
color: "white",
|
||||
flex: "3",
|
||||
margin: 10,
|
||||
paddingLeft: 30,
|
||||
paddingRight: 30,
|
||||
paddingBottom: 30,
|
||||
paddingTop: 30,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
position: "relative",
|
||||
maxHeight: 180,
|
||||
overflow: "hidden",
|
||||
};
|
||||
|
||||
const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
|
||||
|
||||
|
||||
// AppTypes:
|
||||
// 0 = OpenAPI (VALID)
|
||||
@@ -162,7 +115,54 @@ const AppExplorer = (props) => {
|
||||
const classes = useStyles()
|
||||
let navigate = useNavigate()
|
||||
|
||||
const { leftSideBarOpenByClick, } = useContext(Context);
|
||||
const { leftSideBarOpenByClick, themeMode, supportEmail } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
const surfaceColor = "#27292D";
|
||||
const inputColor = theme.palette.textFieldStyle.backgroundColor;
|
||||
|
||||
const chipStyle = {
|
||||
marginTop: 5,
|
||||
backgroundColor: theme.palette.chipStyle.backgroundColor,
|
||||
height: 30,
|
||||
marginRight: 5,
|
||||
paddingLeft: 5,
|
||||
paddingRight: 5,
|
||||
cursor: "pointer",
|
||||
borderColor: theme.palette.chipStyle.borderColor,
|
||||
color: theme.palette.chipStyle.color,
|
||||
};
|
||||
|
||||
const actionListStyle = {
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingTop: 10,
|
||||
marginTop: 5,
|
||||
backgroundColor: inputColor,
|
||||
display: "flex",
|
||||
color: theme.palette.text.primary,
|
||||
maxWidth: 350,
|
||||
minWidth: 350,
|
||||
maxHeight: 54,
|
||||
overflow: "hidden",
|
||||
};
|
||||
|
||||
const boxStyle = {
|
||||
color: theme.palette.text.primary,
|
||||
flex: "3",
|
||||
margin: 10,
|
||||
paddingLeft: 30,
|
||||
paddingRight: 30,
|
||||
paddingBottom: 30,
|
||||
paddingTop: 30,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
position: "relative",
|
||||
maxHeight: 180,
|
||||
overflow: "hidden",
|
||||
};
|
||||
|
||||
const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
|
||||
|
||||
const params = useParams();
|
||||
//var props = JSON.parse(JSON.stringify(defaultprops))
|
||||
@@ -385,9 +385,9 @@ const AppExplorer = (props) => {
|
||||
extraInfo = (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
padding: 15,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
borderRadius: theme.palette?.textFieldStyle.borderRadius,
|
||||
marginBottom: 30,
|
||||
display: "flex",
|
||||
}}
|
||||
@@ -555,7 +555,9 @@ const AppExplorer = (props) => {
|
||||
}}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.chipStyle.backgroundColor,
|
||||
borderColor: theme.palette.chipStyle.borderColor,
|
||||
color: theme.palette.chipStyle.color,
|
||||
borderRadius: 40,
|
||||
minWidth: 80,
|
||||
marginRight: 10,
|
||||
@@ -586,7 +588,9 @@ const AppExplorer = (props) => {
|
||||
disabled={included === false}
|
||||
style={{
|
||||
cursor: included ? "pointer" : "default",
|
||||
color: "white",
|
||||
color: theme.palette.chipStyle.color,
|
||||
borderColor: theme.palette.chipStyle.borderColor,
|
||||
backgroundColor: theme.palette.chipStyle.backgroundColor,
|
||||
borderRadius: 40,
|
||||
minWidth: 80,
|
||||
marginRight: 10,
|
||||
@@ -776,7 +780,7 @@ const AppExplorer = (props) => {
|
||||
if (responseJson.reason !== undefined) {
|
||||
toast("Failed to perform action: "+responseJson.reason);
|
||||
} else {
|
||||
toast("Failed to perform action. Please try again or contact support@shuffler.io");
|
||||
toast(`Failed to perform action. Please try again or contact ${supportEmail}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -3093,7 +3097,7 @@ const AppExplorer = (props) => {
|
||||
margin: 10,
|
||||
padding: 30,
|
||||
backgroundColor: boxStyle.backgroundColor,
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
textAlign: "left",
|
||||
paddingBottom: 50,
|
||||
overflow: "hidden",
|
||||
@@ -3117,12 +3121,12 @@ const AppExplorer = (props) => {
|
||||
style={{ marginBottom: 0, marginLeft: 0, marginRight: 0, minWidth: 800, maxWidth: 800, margin: "auto", }}
|
||||
aria-label="disabled tabs example"
|
||||
>
|
||||
<Tab style={{marginLeft: 0, }} icon={<DescriptionIcon />} label="Docs" />
|
||||
<Tab style={{marginLeft: 0, color: theme.palette.text.primary }} icon={<DescriptionIcon />} label="Docs" />
|
||||
<Tab icon={appType === 0 || appType === 2 ? <OpenInNewIcon /> : <AppsIcon />} label={appType === 0 || appType === 2 ? "Explore the API" : "Try it out"} />
|
||||
|
||||
<Tab icon={<ShowChartIcon />} label="Stats" />
|
||||
<Tab icon={<PolylineIcon />} disabled label="Integrations" />
|
||||
<Tab icon={<PersonIcon />} disabled={userdata.support !== true} label="Creator" value={4} />
|
||||
<Tab icon={<ShowChartIcon />} style={{color: theme.palette.text.primary}} label="Stats" />
|
||||
<Tab icon={<PolylineIcon />} disabled style={{color: theme.palette.text.secondary}} label="Integrations" />
|
||||
<Tab icon={<PersonIcon />} disabled={userdata.support !== true} style={{color: userdata.support !== true ? theme.palette.text.secondary: theme.palette.text.primary}} label="Creator" value={4} />
|
||||
</Tabs>
|
||||
<div style={{ marginTop: 25 }}>
|
||||
{selectedTab === 1 && app.skipped_build == false ? (
|
||||
@@ -3883,12 +3887,12 @@ const AppExplorer = (props) => {
|
||||
</div>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#1a1a1a", backgroundColor: "#ff8544" }}
|
||||
color="primary"
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, }}
|
||||
onClick={() => {
|
||||
updateAppField(selectedApp.id, "sharing", true);
|
||||
setPublishModalOpen(false);
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
Yes
|
||||
</Button>
|
||||
@@ -3919,13 +3923,13 @@ const AppExplorer = (props) => {
|
||||
<Breadcrumbs
|
||||
aria-label="breadcrumb"
|
||||
separator="›"
|
||||
style={{ color: "white", marginLeft: 15, flex: 100 }}
|
||||
style={{ color: theme.palette.text.primary, marginLeft: 15, flex: 100 }}
|
||||
>
|
||||
<Link
|
||||
to="/search"
|
||||
style={{ textDecoration: "none", color: "inherit" }}
|
||||
>
|
||||
<h2 style={{ color: "rgba(255,255,255,0.5)" }}>
|
||||
<h2 style={{ color: theme.palette.text.primary }}>
|
||||
<AppsIcon style={{ marginRight: 10 }} />
|
||||
Apps
|
||||
</h2>
|
||||
@@ -3971,9 +3975,7 @@ const AppExplorer = (props) => {
|
||||
) : null}
|
||||
{appType === 0 || appType === 2 ? (
|
||||
<IconButton
|
||||
color="primary"
|
||||
style={{ marginRight: 20 }}
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
const data = openapi;
|
||||
let exportFileDefaultName = name + ".json";
|
||||
@@ -4020,7 +4022,7 @@ const AppExplorer = (props) => {
|
||||
}}
|
||||
>
|
||||
<Tooltip title="Download OpenAPI" placement="top">
|
||||
<CloudDownloadIcon color="secondary" />
|
||||
<CloudDownloadIcon color={theme.palette.text.primary} />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
) : null}
|
||||
@@ -4036,7 +4038,7 @@ const AppExplorer = (props) => {
|
||||
}}
|
||||
>
|
||||
<Tooltip title="Public Authentication link for the current Organization. Times out every 24 hours." placement="top">
|
||||
<LockOpenIcon />
|
||||
<LockOpenIcon color={theme.palette.text.primary}/>
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
: null}
|
||||
@@ -4197,8 +4199,8 @@ const AppExplorer = (props) => {
|
||||
}}
|
||||
style={{
|
||||
width: 150,
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.text.primary,
|
||||
height: 40,
|
||||
marginTop: 5
|
||||
}}
|
||||
@@ -4213,7 +4215,7 @@ const AppExplorer = (props) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={data}
|
||||
style={{ backgroundColor: inputColor, color: "white", display: 'flex' }}
|
||||
sx={{ backgroundColor: inputColor, color: theme.palette.text.primary, display: 'flex', "&:hover": { backgroundColor: theme.palette.hoverColor } }}
|
||||
value={data}
|
||||
>
|
||||
{data}
|
||||
@@ -4373,8 +4375,8 @@ const AppExplorer = (props) => {
|
||||
style={{
|
||||
borderRadius: 25,
|
||||
fontSize: 11,
|
||||
color: "white",
|
||||
backgroundColor: "rgba(255,255,255,0)",
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
border: "1px solid #ddf4e1",
|
||||
textTransform: "none",
|
||||
marginLeft: 4,
|
||||
@@ -4466,6 +4468,11 @@ const AppExplorer = (props) => {
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
}}
|
||||
sx={{
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CardActionArea
|
||||
component={Link}
|
||||
@@ -4553,6 +4560,11 @@ const AppExplorer = (props) => {
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
}}
|
||||
sx={{
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.hoverColor,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CardActionArea
|
||||
component={Link}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useContext, useCallback, memo, useMemo, useRef } from "react";
|
||||
import theme from "../theme.jsx";
|
||||
import {getTheme} from "../theme.jsx";
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
@@ -55,6 +55,8 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
|
||||
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 = `/apps/${data.id}`
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
var canEditApp = userdata?.support || userdata?.id === data?.owner ||
|
||||
(userdata?.admin === "true" && userdata?.active_org?.id === data?.reference_org) || data?.contributors?.includes(userdata?.id)
|
||||
@@ -104,7 +106,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
|
||||
display: "flex",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
width: '100%',
|
||||
backgroundColor: mouseHoverIndex === index ? "#2F2F2F" : "#212121"
|
||||
backgroundColor: mouseHoverIndex === index ? theme.palette.hoverColor : theme.palette.platformColor,
|
||||
}}
|
||||
onClick={() => {
|
||||
handleAppClick(data);
|
||||
@@ -150,7 +152,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
color: '#F1F1F1'
|
||||
color: theme.palette.text.primary,
|
||||
}}>
|
||||
{data.name.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase())}
|
||||
</div>
|
||||
@@ -161,7 +163,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
marginLeft: 8,
|
||||
color: "rgba(158, 158, 158, 1)"
|
||||
color: theme.palette.text.secondary,
|
||||
}}>
|
||||
{data.categories ? data.categories.join(", ") : "NA"}
|
||||
</div>
|
||||
@@ -172,7 +174,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
|
||||
whiteSpace: "nowrap",
|
||||
width: "100%",
|
||||
marginLeft: 8,
|
||||
color: "rgba(158, 158, 158, 1)",
|
||||
color: theme.palette.text.secondary,
|
||||
display: "flex",
|
||||
justifyContent: 'space-between',
|
||||
paddingRight: 15,
|
||||
@@ -202,7 +204,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
|
||||
}}>
|
||||
{
|
||||
canEditApp ? (
|
||||
<button style={{ backgroundColor: "rgba(73, 73, 73, 1)", border: "none", cursor: "pointer", color: "white", borderRadius: 3, display: "flex", alignItems: "center", justifyContent: "center", height: 35 }}
|
||||
<Button style={{ border: "none", cursor: "pointer", borderRadius: 3, display: "flex", alignItems: "center", justifyContent: "center", height: 35 }}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -211,11 +213,13 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
|
||||
navigate(editUrl)
|
||||
}
|
||||
}}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
>
|
||||
<EditIcon />
|
||||
</button>
|
||||
</Button>
|
||||
) : (
|
||||
<button style={{ backgroundColor: "rgba(73, 73, 73, 1)", border: "none", cursor: "pointer", color: "white", borderRadius: 3, display: "flex", alignItems: "center", justifyContent: "center", height: 35 }}
|
||||
<Button variant="contained" color="secondary" style={{ border: "none", cursor: "pointer", color: "white", borderRadius: 3, display: "flex", alignItems: "center", justifyContent: "center", height: 35 }}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -224,26 +228,23 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
|
||||
}}
|
||||
>
|
||||
<ForkRightIcon />
|
||||
</button>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
<Button
|
||||
disabled={data?.reference_org === userdata?.active_org?.id}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
className="deactivate-button"
|
||||
sx={{
|
||||
width: 110,
|
||||
height: 35,
|
||||
borderRadius: 0.75,
|
||||
bgcolor: "rgba(73, 73, 73, 1)",
|
||||
color: "rgba(241, 241, 241, 1)",
|
||||
textTransform: "none",
|
||||
fontSize: 16,
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
transition: "background-color 0.3s ease",
|
||||
"&:hover": {
|
||||
bgcolor: "rgba(93, 93, 93, 1)",
|
||||
},
|
||||
}}
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onMouseUp={(e) => e.stopPropagation()}
|
||||
@@ -308,6 +309,8 @@ const Hits = ({
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||
const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]);
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
useEffect(() => {
|
||||
var baseurl = globalUrl;
|
||||
@@ -507,7 +510,7 @@ const Hits = ({
|
||||
overflow: "hidden",
|
||||
display: "flex",
|
||||
width: '100%',
|
||||
backgroundColor: hoverEffect === index ? "#2F2F2F" : "#212121",
|
||||
backgroundColor: hoverEffect === index ? theme.palette.hoverColor : theme.palette.platformColor,
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
}}
|
||||
onClick={() => {
|
||||
@@ -550,7 +553,7 @@ const Hits = ({
|
||||
maxWidth: "90%",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
color: '#F1F1F1'
|
||||
color: theme.palette.text.primary
|
||||
}}
|
||||
>
|
||||
{(allActivatedAppIds && allActivatedAppIds.includes(data.objectID)) && <Box sx={{ width: 8, height: 8, backgroundColor: "#02CB70", borderRadius: '50%' }} />}
|
||||
@@ -558,7 +561,7 @@ const Hits = ({
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
color: '#F1F1F1'
|
||||
color: theme.palette.text.primary,
|
||||
}}>
|
||||
{normalizedString(data.name)}
|
||||
</div>
|
||||
@@ -569,7 +572,7 @@ const Hits = ({
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
color: "rgba(158, 158, 158, 1)",
|
||||
color: theme.palette.text.secondary,
|
||||
marginTop: 5,
|
||||
}}
|
||||
>
|
||||
@@ -600,12 +603,12 @@ const Hits = ({
|
||||
componentsProps={{
|
||||
tooltip: {
|
||||
sx: {
|
||||
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||
color: "rgba(241, 241, 241, 1)",
|
||||
backgroundColor: theme.palette.tooltip.backgroundColor,
|
||||
color: theme.palette.tooltip.color,
|
||||
width: "auto",
|
||||
height: "auto",
|
||||
fontSize: 16,
|
||||
border: "1px solid rgba(73, 73, 73, 1)",
|
||||
border: theme.palette.tooltip.border,
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -650,15 +653,15 @@ const Hits = ({
|
||||
<div>
|
||||
{allActivatedAppIds && allActivatedAppIds?.includes(data.objectID) ? (
|
||||
<Button
|
||||
style={{
|
||||
width: 110,
|
||||
height: 35,
|
||||
borderRadius: 4,
|
||||
backgroundColor: "rgba(73, 73, 73, 1)",
|
||||
color: "rgba(241, 241, 241, 1)",
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
sx={{
|
||||
width: "110px",
|
||||
height: "35px",
|
||||
borderRadius: "4px",
|
||||
textTransform: "none",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontSize: 16,
|
||||
fontSize: "16px",
|
||||
}}
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onMouseUp={(e) => e.stopPropagation()}
|
||||
@@ -671,9 +674,9 @@ const Hits = ({
|
||||
) : (
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
backgroundColor: "#FF8544",
|
||||
color: "black",
|
||||
width: 102,
|
||||
height: 35,
|
||||
borderRadius: 4,
|
||||
@@ -719,6 +722,8 @@ const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
|
||||
const inputRef = useRef(null);
|
||||
const [localQuery, setLocalQuery] = useState(searchQuery);
|
||||
const location = useLocation();
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
// Initialize search when component mounts or when switching to Discover tab
|
||||
useEffect(() => {
|
||||
if (searchQuery) {
|
||||
@@ -779,7 +784,8 @@ const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
borderRadius: 4,
|
||||
height: 45
|
||||
height: 45,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
},
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
@@ -809,6 +815,8 @@ const CustomHits = connectHits(Hits);
|
||||
|
||||
// Custom Category Dropdown Component
|
||||
const CategoryDropdown = ({ items, currentRefinement, refine }) => {
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
const handleChange = (event) => {
|
||||
const value = event.target.value;
|
||||
refine(value);
|
||||
@@ -823,7 +831,7 @@ const CategoryDropdown = ({ items, currentRefinement, refine }) => {
|
||||
onChange={handleChange}
|
||||
displayEmpty
|
||||
multiple
|
||||
style={{ borderRadius: 4, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1 }}
|
||||
style={{ borderRadius: 4, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1, backgroundColor: theme.palette.textFieldStyle.backgroundColor, color: theme.palette.textFieldStyle.color }}
|
||||
renderValue={(selected) => {
|
||||
if (selected.length === 0) return 'All Categories';
|
||||
return (
|
||||
@@ -875,6 +883,9 @@ const LabelDropdown = ({ items, currentRefinement, refine }) => {
|
||||
refine(value);
|
||||
};
|
||||
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
return (
|
||||
<div style={{ position: 'relative', width: '100%' }}>
|
||||
<Select
|
||||
@@ -884,7 +895,7 @@ const LabelDropdown = ({ items, currentRefinement, refine }) => {
|
||||
onChange={handleChange}
|
||||
displayEmpty
|
||||
multiple
|
||||
style={{ borderRadius: 4, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1 }}
|
||||
style={{ borderRadius: 4, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1, backgroundColor: theme.palette.textFieldStyle.backgroundColor, color: theme.palette.textFieldStyle.color }}
|
||||
renderValue={(selected) => {
|
||||
if (selected.length === 0) return 'All Labels';
|
||||
return (
|
||||
@@ -930,6 +941,7 @@ const LabelDropdown = ({ items, currentRefinement, refine }) => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const CustomLabelDropdown = connectRefinementList(LabelDropdown);
|
||||
|
||||
|
||||
@@ -970,6 +982,8 @@ const filterApps = (apps, searchQuery, selectedCategory, selectedLabel) => {
|
||||
|
||||
const LoginPrompt = () => {
|
||||
const navigate = useNavigate();
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
return (
|
||||
<div style={{
|
||||
display: "flex",
|
||||
@@ -1006,9 +1020,11 @@ const LoginPrompt = () => {
|
||||
|
||||
// Add this new component for the app skeleton
|
||||
const AppSkeleton = () => {
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
return (
|
||||
<Paper elevation={0} style={{
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
width: "100%",
|
||||
height: 120,
|
||||
borderRadius: 4,
|
||||
@@ -1025,7 +1041,7 @@ const AppSkeleton = () => {
|
||||
height={90}
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
backgroundColor: "rgba(255, 255, 255, 0.1)"
|
||||
backgroundColor: theme.palette.loaderColor
|
||||
}}
|
||||
/>
|
||||
<div style={{
|
||||
@@ -1039,19 +1055,19 @@ const AppSkeleton = () => {
|
||||
variant="text"
|
||||
width="40%"
|
||||
height={24}
|
||||
style={{ backgroundColor: "rgba(255, 255, 255, 0.1)" }}
|
||||
style={{ backgroundColor: theme.palette.loaderColor }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="text"
|
||||
width="60%"
|
||||
height={20}
|
||||
style={{ backgroundColor: "rgba(255, 255, 255, 0.1)" }}
|
||||
style={{ backgroundColor: theme.palette.loaderColor }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="text"
|
||||
width="30%"
|
||||
height={20}
|
||||
style={{ backgroundColor: "rgba(255, 255, 255, 0.1)" }}
|
||||
style={{ backgroundColor: theme.palette.loaderColor }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1117,6 +1133,9 @@ const Apps2 = (props) => {
|
||||
const [validation, setValidation] = useState(null);
|
||||
const [createAppModalOpen, setCreateAppModalOpen] = useState(false);
|
||||
|
||||
const {themeMode, brandColor} = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
const baseRepository = "https://github.com/frikky/shuffle-apps";
|
||||
|
||||
const isCloud =
|
||||
@@ -1373,7 +1392,6 @@ const Apps2 = (props) => {
|
||||
// setSelectedAction({});
|
||||
// }
|
||||
}
|
||||
|
||||
if (privateapps.length > 0 && storageApps.length === 0) {
|
||||
try {
|
||||
localStorage.setItem("apps", JSON.stringify(privateapps))
|
||||
@@ -1869,13 +1887,13 @@ const Apps2 = (props) => {
|
||||
}
|
||||
|
||||
const tabActive = {
|
||||
borderBottom: "5px solid #FF8544",
|
||||
borderBottom: `5px solid ${theme.palette.primary.main}`,
|
||||
borderRadius: "2px",
|
||||
color: "#FF8544"
|
||||
color: theme.palette.primary.main,
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ paddingTop: 70, paddingLeft: leftSideBarOpenByClick ? 200 : 0, transition: "padding-left 0.3s ease", backgroundColor: "#1A1A1A", fontFamily: theme?.typography?.fontFamily, zoom: 0.7, }}>
|
||||
<div style={{ paddingTop: 70, paddingLeft: leftSideBarOpenByClick ? 200 : 0, transition: "padding-left 0.3s ease", backgroundColor: theme.palette.backgroundColor, fontFamily: theme?.typography?.fontFamily, zoom: 0.7, }}>
|
||||
<InstantSearch searchClient={searchClient} indexName="appsearch">
|
||||
<AppModal
|
||||
open={openModal}
|
||||
@@ -1984,7 +2002,7 @@ const Apps2 = (props) => {
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ borderBottom: '1px solid gray', marginBottom: 30 }}>
|
||||
<div style={{ borderBottom: themeMode === "dark" ? "1px solid #808080" : theme.palette.defaultBorder, marginBottom: 30 }}>
|
||||
<Tabs
|
||||
value={currTab}
|
||||
onChange={(event, newTab) => handleTabChange(event, newTab)}
|
||||
@@ -2034,6 +2052,10 @@ const Apps2 = (props) => {
|
||||
value={searchQuery}
|
||||
id="shuffle_search_field"
|
||||
onChange={handleSearchChange}
|
||||
style={{
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
@@ -2043,7 +2065,10 @@ const Apps2 = (props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
borderRadius: 4,
|
||||
height: 45
|
||||
height: 45,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontSize: 18,
|
||||
},
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
@@ -2087,7 +2112,9 @@ const Apps2 = (props) => {
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
height: 45,
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
fontSize: 18,
|
||||
}}
|
||||
renderValue={(selected) => {
|
||||
if (selected.length === 0) return 'All Categories';
|
||||
@@ -2152,7 +2179,9 @@ const Apps2 = (props) => {
|
||||
style={{
|
||||
borderRadius: 4,
|
||||
height: 45,
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
fontSize: 18,
|
||||
}}
|
||||
renderValue={(selected) => {
|
||||
if (selected.length === 0) return 'All Labels';
|
||||
@@ -2211,13 +2240,11 @@ const Apps2 = (props) => {
|
||||
width: '100%',
|
||||
borderRadius: '4px',
|
||||
textTransform: 'none',
|
||||
backgroundColor: "#FF8544",
|
||||
color: "#1A1A1A",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontSize: 16,
|
||||
fontWeight: 500
|
||||
}}
|
||||
startIcon={<AddIcon style={{ color: "#1A1A1A" }} />}
|
||||
startIcon={<AddIcon />}
|
||||
>
|
||||
Create an App
|
||||
</Button>
|
||||
|
||||
+88
-26
@@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useLayoutEffect, useRef, useState, useContext, memo } from "react"
|
||||
import React, { useEffect, useLayoutEffect, useRef, useState, useContext, memo, } from "react"
|
||||
import { toast } from 'react-toastify';
|
||||
import Markdown from 'react-markdown'
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import ReactJson from "react-json-view-ssr";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { BrowserView, MobileView } from "react-device-detect";
|
||||
@@ -28,7 +28,8 @@ import {
|
||||
DialogTitle,
|
||||
Box,
|
||||
DialogContent,
|
||||
InputAdornment
|
||||
InputAdornment,
|
||||
CircularProgress
|
||||
} from "@mui/material";
|
||||
import {
|
||||
Link as LinkIcon,
|
||||
@@ -171,6 +172,9 @@ export const Img = (props) => {
|
||||
var height = "auto"
|
||||
var width = isArticlePage ? 1000 : isFormPage ? 400: 750
|
||||
|
||||
const { themeMode } = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const docsImageStyle = {
|
||||
border: isFormPage ? null : "1px solid rgba(255,255,255,0.3)",
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
@@ -215,6 +219,8 @@ export const CodeHandler = (props) => {
|
||||
const propvalue = props.value !== undefined && props.value !== null ? props.value : props.children !== undefined && props.children !== null && props.children.length > 0 ? props.children[0] : ""
|
||||
|
||||
const validate = validateJson(propvalue)
|
||||
const {themeMode } = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
var newprop = propvalue
|
||||
if (validate.valid === false) {
|
||||
@@ -293,6 +299,7 @@ const Docs = (defaultprops) => {
|
||||
|
||||
let navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const pathname = location.pathname
|
||||
// Quickfix for react router 5 -> 6
|
||||
const params = useParams();
|
||||
//var props = JSON.parse(JSON.stringify(defaultprops))
|
||||
@@ -301,6 +308,8 @@ const Docs = (defaultprops) => {
|
||||
props.match.params = params
|
||||
|
||||
//console.log("PARAMS: ", params)
|
||||
const { themeMode } = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const [mobile, setMobile] = useState(serverMobile === true || isMobile === true ? true : false);
|
||||
const [data, setData] = useState("");
|
||||
@@ -326,9 +335,37 @@ const Docs = (defaultprops) => {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const [activeSubItem, setActiveSubItem] = useState(false);
|
||||
const headingElementsRef = useRef({})
|
||||
const [hasRedirected, setHasRedirected] = useState(false)
|
||||
var isArticlePage = window.location.pathname.includes("/articles/") || window.location.pathname === "/articles" ? true : false;
|
||||
const searchFieldRef = useRef(null);
|
||||
|
||||
const handleDocRedirectForPartners = () => {
|
||||
if (hasRedirected) return;
|
||||
|
||||
if (
|
||||
userdata &&
|
||||
userdata?.org_status?.includes("integration_partner") &&
|
||||
userdata?.active_org?.branding?.documentation_link?.length > 0
|
||||
) {
|
||||
const docLink = userdata?.active_org?.branding?.documentation_link;
|
||||
if (docLink && docLink !== "") {
|
||||
setHasRedirected(true);
|
||||
if (docLink.startsWith('http')) {
|
||||
window.location.replace(docLink);
|
||||
} else {
|
||||
navigate(docLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoggedIn && isLoaded) {
|
||||
handleDocRedirectForPartners()
|
||||
}
|
||||
|
||||
}, [isLoggedIn, isLoaded]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchDocList();
|
||||
@@ -353,6 +390,8 @@ const Docs = (defaultprops) => {
|
||||
navigate('/docs/apps#app-creation-introduction')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}, [location]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -501,19 +540,25 @@ const Docs = (defaultprops) => {
|
||||
}
|
||||
}}
|
||||
PaperProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
minWidth: 750,
|
||||
sx: {
|
||||
color: theme.palette.DialogStyle.color,
|
||||
minWidth: "750px",
|
||||
minHeight: "180px",
|
||||
maxHeight: "85vh",
|
||||
borderRadius: 16,
|
||||
borderRadius: theme.palette.DialogStyle.borderRadius,
|
||||
border: "1px solid var(--Container-Stroke, #494949)",
|
||||
background: "var(--Container, #000000)",
|
||||
background: theme.palette.DialogStyle.backgroundColor,
|
||||
boxShadow: "0px 16px 24px 8px rgba(0, 0, 0, 0.25)",
|
||||
position: "fixed",
|
||||
top: "70px",
|
||||
left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
'& .MuiDialogContent-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
'& .MuiDialogTitle-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
},
|
||||
}}
|
||||
sx={{
|
||||
@@ -526,7 +571,7 @@ const Docs = (defaultprops) => {
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", px: 2, pr: 3, pt: 2 }}>
|
||||
<DialogTitle
|
||||
sx={{
|
||||
color: "var(--Paragraph-text, #C8C8C8)",
|
||||
color: theme.palette.DialogStyle.color,
|
||||
p: 0,
|
||||
m: 0,
|
||||
ml: 1.5,
|
||||
@@ -594,7 +639,7 @@ const Docs = (defaultprops) => {
|
||||
}
|
||||
|
||||
const SidebarPaperStyle = {
|
||||
backgroundColor: isArticlePage ? "transparent" : "rgb(26,26,26)",
|
||||
backgroundColor: isArticlePage ? "transparent" : theme.palette.backgroundColor,
|
||||
border: isArticlePage ? "none" : undefined,
|
||||
borderRadius: isArticlePage ? "none" : undefined,
|
||||
boxShadow: isArticlePage ? "none" : undefined,
|
||||
@@ -663,9 +708,9 @@ const Docs = (defaultprops) => {
|
||||
extraInfo = (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
padding: 15,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
borderRadius: theme.palette?.textFieldStyle.borderRadius,
|
||||
marginBottom: isArticlePage ? 25 : 30,
|
||||
display: "flex",
|
||||
}}
|
||||
@@ -679,7 +724,7 @@ const Docs = (defaultprops) => {
|
||||
href={selectedMeta.link}
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
>
|
||||
<Button style={{ color: "white", }} variant="outlined" color="secondary">
|
||||
<Button variant="outlined" color="secondary">
|
||||
<EditIcon /> Edit
|
||||
</Button>
|
||||
</a>
|
||||
@@ -788,7 +833,7 @@ const Docs = (defaultprops) => {
|
||||
paddingLeft: "0.3em", rotate: "-30deg",
|
||||
paddingTop: "0.9em", display: props.level === 1 ? "none" : "block",
|
||||
}}>
|
||||
<LinkIcon />
|
||||
<LinkIcon style={{color: theme.palette.textColor}} />
|
||||
</Link>
|
||||
</div>
|
||||
{isArticlePage ? (userdata?.support ? extraInfo : "") : extraInfo}
|
||||
@@ -1028,13 +1073,12 @@ const Docs = (defaultprops) => {
|
||||
}
|
||||
|
||||
const markdownStyle = {
|
||||
color: "rgba(255, 255, 255, 0.90)",
|
||||
color: theme.palette.textColor,
|
||||
overflow: "hidden",
|
||||
paddingBottom: 100,
|
||||
margin: "auto",
|
||||
maxWidth: "100%",
|
||||
minWidth: "100%",
|
||||
overflow: "hidden",
|
||||
fontSize: isMobile ? "1.3rem" : "1.1rem",
|
||||
};
|
||||
|
||||
@@ -1188,6 +1232,7 @@ const Docs = (defaultprops) => {
|
||||
const activeHrefStyleToc2 = {
|
||||
...hrefStyleToc2,
|
||||
color: "#f86a3e",
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
};
|
||||
|
||||
const activeListItemStyle = {
|
||||
@@ -1228,9 +1273,10 @@ const Docs = (defaultprops) => {
|
||||
</InputAdornment>
|
||||
),
|
||||
style: {
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
borderRadius: 4,
|
||||
color: "white",
|
||||
fontSize: 18,
|
||||
color: theme.palette.textColor,
|
||||
},
|
||||
}}
|
||||
style={{
|
||||
@@ -1290,16 +1336,17 @@ const Docs = (defaultprops) => {
|
||||
>
|
||||
<ListItemText
|
||||
style={{
|
||||
color: itemMatching ? "#f86a3e" : "inherit",
|
||||
color: itemMatching ? "#f86a3e" : theme.palette.textColor,
|
||||
flex: 1,
|
||||
}}
|
||||
primary={
|
||||
<Typography
|
||||
variant="body1"
|
||||
style={{
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
color : "inherit",
|
||||
textOverflow: "ellipsis",
|
||||
fontSize: "18px",
|
||||
}}
|
||||
>
|
||||
{newname}
|
||||
@@ -1371,7 +1418,7 @@ const Docs = (defaultprops) => {
|
||||
)}
|
||||
{tocLines.length > 0 ?
|
||||
(
|
||||
<h4 style={{ fontWeight: 600, margin: 0, fontSize: "16px", marginBottom: "8px" }}>Table Of Content</h4>
|
||||
<h4 style={{ fontWeight: 600, margin: 0, fontSize: "16px", marginBottom: "8px", color: theme.palette.text.primary, }}>Table Of Content</h4>
|
||||
|
||||
) : null}
|
||||
<div
|
||||
@@ -1393,16 +1440,17 @@ const Docs = (defaultprops) => {
|
||||
paddingLeft: isArticlePage ? "0" : "8px",
|
||||
paddingRight: isArticlePage ? "0" : "8px",
|
||||
lineHeight: "20px",
|
||||
color: activeId === data.id ? "#f86a3e" : "inherit",
|
||||
}}
|
||||
onClick={(e) => {
|
||||
handleCollapse(index)
|
||||
setActiveId(data.id)
|
||||
}}
|
||||
>
|
||||
<Typography style={{ fontSize: 14, fontWeight: 400, color: activeId === data.id ? "#f86a3e" : theme.palette.textColor, }}>
|
||||
{data.title}
|
||||
</Typography>
|
||||
{data.items.length > 0 ? (
|
||||
<>{isopen == index ? <ExpandMoreIcon /> : <KeyboardArrowRightIcon />}</>
|
||||
<>{isopen === index ? <ExpandMoreIcon style={{color: theme.palette.text.secondary}} /> : <KeyboardArrowRightIcon style={{color: theme.palette.text.secondary}} />}</>
|
||||
) : null}
|
||||
</ListItemButton>
|
||||
{
|
||||
@@ -1414,7 +1462,7 @@ const Docs = (defaultprops) => {
|
||||
return (
|
||||
<ListItemButton
|
||||
key={i}
|
||||
style={activeSubItem === d.id ? activeHrefStyleToc2 : hrefStyleToc2}
|
||||
style={activeSubItem === d.id ? activeHrefStyleToc2 : {...hrefStyleToc2, color: theme.palette.text.secondary, fontFamily: theme.typography.fontFamily,}}
|
||||
href={`#${d.id}`}
|
||||
onClick={(e) => {
|
||||
// e.preventDefault()
|
||||
@@ -1577,7 +1625,7 @@ const Docs = (defaultprops) => {
|
||||
|
||||
// Padding and zIndex etc set because of footer in cloud.
|
||||
const loadedCheck = (
|
||||
<DocsWrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
|
||||
<DocsWrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded} userdata={userdata}>
|
||||
<DocsContent postDataBrowser={postDataBrowser} postDataMobile={postDataMobile}/>
|
||||
</DocsWrapper>
|
||||
);
|
||||
@@ -1589,6 +1637,8 @@ return <div>{loadedCheck}</div>;
|
||||
export default Docs;
|
||||
|
||||
const DocsContent = memo(({postDataBrowser, postDataMobile}) => {
|
||||
const { themeMode } = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
return(
|
||||
<div style={{fontFamily: theme?.palette?.fontFamily}}>
|
||||
<BrowserView>{postDataBrowser}</BrowserView>
|
||||
@@ -1596,10 +1646,22 @@ const DocsContent = memo(({postDataBrowser, postDataMobile}) => {
|
||||
</div>
|
||||
)})
|
||||
|
||||
const DocsWrapper = memo(({isLoggedIn, isLoaded, children })=>{
|
||||
const DocsWrapper = memo(({isLoggedIn, isLoaded, children, userdata })=>{
|
||||
|
||||
const { leftSideBarOpenByClick, windowWidth } = useContext(Context);
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoaded && isLoggedIn && userdata?.org_status?.includes("integration_partner") && userdata?.active_org?.branding.documentation_link?.length > 0) {
|
||||
window.location.href = userdata?.active_org?.branding.documentation_link;
|
||||
}
|
||||
}, [isLoaded, isLoggedIn, userdata]);
|
||||
|
||||
if (isLoaded && isLoggedIn && userdata?.org_status?.includes("integration_partner") && userdata?.active_org?.branding.documentation_link?.length > 0) {
|
||||
return <CircularProgress style={{position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)"}} />;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
marginTop: window.location.pathname.includes("/articles/") ? 50 : undefined,
|
||||
|
||||
@@ -297,7 +297,7 @@ const LoginPage = props => {
|
||||
const [showPassword, setShowPassword] = useState(false)
|
||||
const [ssoUrl, setSSOUrl] = useState("");
|
||||
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "migration.shuffler.io";
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "migration.shuffler.io" || window.location.host === "sandbox.shuffler.io";
|
||||
const parsedsearch = serverside === true ? "" : window.location.search
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
import React, {useState, useEffect} from 'react';
|
||||
import React, {useState, useEffect, useContext} from 'react';
|
||||
import ReactDOM from "react-dom"
|
||||
|
||||
import ReactJson from "react-json-view-ssr";
|
||||
@@ -48,6 +48,7 @@ import {
|
||||
Edit as EditIcon,
|
||||
Polyline as PolylineIcon,
|
||||
} from '@mui/icons-material';
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
|
||||
const hrefStyle = {
|
||||
color: "white",
|
||||
@@ -58,6 +59,7 @@ const hrefStyle = {
|
||||
const RunWorkflow = (defaultprops) => {
|
||||
const { globalUrl, userdata, isLoaded, isLoggedIn, setIsLoggedIn, setCookie, register, serverside } = defaultprops;
|
||||
|
||||
const { supportEmail } = useContext(Context);
|
||||
let navigate = useNavigate();
|
||||
const [_, setUpdate] = useState(""); // Used to force rendring, don't remove
|
||||
const [explorerUi, setExplorerUi] = useState(false)
|
||||
@@ -471,7 +473,7 @@ const RunWorkflow = (defaultprops) => {
|
||||
}
|
||||
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
toast("This Form is not available for you to run. If you this is an error, contact support@shuffler.io with a link to this form")
|
||||
toast(`This Form is not available for you to run. If you this is an error, contact ${supportEmail} with a link to this form`)
|
||||
}
|
||||
|
||||
return response.json()
|
||||
@@ -627,7 +629,7 @@ const RunWorkflow = (defaultprops) => {
|
||||
}
|
||||
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
toast("This Form is not available to you. If you think this is an error, please contact support@shuffler.io with the URL.")
|
||||
toast(`This Form is not available to you. If you think this is an error, please contact ${supportEmail} with the URL.`)
|
||||
}
|
||||
|
||||
return response.json()
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useContext, useState } from "react";
|
||||
|
||||
import { Typography, CircularProgress } from "@mui/material";
|
||||
import theme from '../theme.jsx';
|
||||
|
||||
import { red, } from "../views/AngularWorkflow.jsx"
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
const SetAuthentication = (props) => {
|
||||
const { globalUrl } = props;
|
||||
|
||||
const { supportEmail } = useContext(Context);
|
||||
var headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
@@ -328,7 +329,7 @@ const SetAuthentication = (props) => {
|
||||
<b>{failed ? "Failed auth. Error: " : ""}</b> {response}
|
||||
<br/>
|
||||
<br/>
|
||||
{failed ? "If the error persists, try to use fewer scopes. Contact support@shuffler.io if you need further assistance, and include the current URL and a screenshot. You may now close this window." : ""}
|
||||
{failed ? `If the error persists, try to use fewer scopes. Contact ${supportEmail} if you need further assistance, and include the current URL and a screenshot. You may now close this window.` : ""}
|
||||
</Typography>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import theme from '../theme.jsx';
|
||||
import {getTheme} from '../theme.jsx';
|
||||
import {
|
||||
Grid,
|
||||
Typography,
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
//import { useAlert
|
||||
import { ToastContainer, toast } from "react-toastify";
|
||||
import "../codeeditor-index.css";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
import { FileCopy, Visibility, VisibilityOff } from "@mui/icons-material";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
@@ -40,6 +41,8 @@ const Settings = (props) => {
|
||||
const [MFARequired, setMFARequired] = React.useState(false);
|
||||
const [image2FA, setImage2FA] = React.useState("");
|
||||
const [value2FA, setValue2FA] = React.useState("");
|
||||
const {themeMode, supportEmail} = useContext(Context);
|
||||
const theme = getTheme(themeMode);
|
||||
|
||||
// const [file, setFile] = React.useState("");
|
||||
// const [fileBase64, setFileBase64] = React.useState(
|
||||
@@ -83,7 +86,7 @@ const Settings = (props) => {
|
||||
|
||||
const boxStyle = {
|
||||
flex: "1",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
position: "relative",
|
||||
marginLeft: "10px",
|
||||
marginRight: "10px",
|
||||
@@ -213,8 +216,8 @@ const Settings = (props) => {
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
zIndex: "9999",
|
||||
backgroundColor: "#1a1a1a",
|
||||
color: "white",
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
color: theme.palette.text.primary,
|
||||
padding: 20,
|
||||
borderRadius: 5,
|
||||
boxShadow: "0 0 10px rgba(0, 0, 0, 0.3)",
|
||||
@@ -223,7 +226,7 @@ const Settings = (props) => {
|
||||
};
|
||||
|
||||
const closeIconButtonStyling = {
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
border: "none",
|
||||
backgroundColor: "transparent",
|
||||
marginLeft: "90%",
|
||||
@@ -243,7 +246,7 @@ const Settings = (props) => {
|
||||
width: "100%",
|
||||
fontSize: 16,
|
||||
backgroundColor: disabled ? "gray" : "red",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
cursor: disabled === false && "pointer",
|
||||
};
|
||||
const checkboxStyle = {
|
||||
@@ -381,7 +384,7 @@ const Settings = (props) => {
|
||||
className="ais-RefinementList-checkbox"
|
||||
onClick={handleCheckBoxEvent}
|
||||
/>
|
||||
<label style={{ fontSize: "16px", color: "white" }}>
|
||||
<label style={{ fontSize: "16px", color: theme.palette.text.primary }}>
|
||||
I have read the above information and I agree to it completely
|
||||
</label>
|
||||
</div>
|
||||
@@ -410,7 +413,7 @@ const Settings = (props) => {
|
||||
endAdornment: (
|
||||
<IconButton
|
||||
onClick={handlePasswordVisibility}
|
||||
style={{color:"white"}}
|
||||
style={{color:theme.palette.text.primary}}
|
||||
>
|
||||
{showPassword ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
@@ -704,7 +707,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -732,7 +735,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -757,7 +760,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -788,7 +791,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -806,7 +809,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
endAdornment: (
|
||||
<>
|
||||
@@ -857,7 +860,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style:{
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -877,7 +880,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style:{
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -899,7 +902,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style:{
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -919,7 +922,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style:{
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -954,7 +957,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -979,7 +982,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -1002,7 +1005,7 @@ const Settings = (props) => {
|
||||
InputProps={{
|
||||
style: {
|
||||
height: "50px",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
@@ -1046,7 +1049,7 @@ const Settings = (props) => {
|
||||
{isCloud ?
|
||||
<span>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
By <a href="/creators" target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}}>joining the Creator Incentive Program</a> and connecting your Github account, you agree to our <a href="/docs/terms_of_service" target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}}>Terms of Service</a>, and acknowledge that your non-sensitive data will be turned into a <a target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}} href="https://shuffler.io/creators">creator account</a>. This enables you to earn a passive income from Shuffle. This IS reversible. Support: support@shuffler.io
|
||||
By <a href="/creators" target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}}>joining the Creator Incentive Program</a> and connecting your Github account, you agree to our <a href="/docs/terms_of_service" target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}}>Terms of Service</a>, and acknowledge that your non-sensitive data will be turned into a <a target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}} href="https://shuffler.io/creators">creator account</a>. This enables you to earn a passive income from Shuffle. This IS reversible. Support: {supportEmail}
|
||||
</Typography>
|
||||
<Button
|
||||
style={{ height: 40, marginTop: 10 }}
|
||||
@@ -1133,7 +1136,7 @@ const Settings = (props) => {
|
||||
height: "60px",
|
||||
marginTop: "10px",
|
||||
backgroundColor: "#d52b2b",
|
||||
color: "white",
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
// variant="contained"
|
||||
// color="primary"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
|
||||
import ReactGA from "react-ga4";
|
||||
import {
|
||||
@@ -15,10 +15,11 @@ import { ToastContainer, toast } from "react-toastify"
|
||||
import AuthenticationOauth2 from "../components/Oauth2Auth.jsx";
|
||||
import AuthenticationWindow from "../components/AuthenticationWindow.jsx";
|
||||
import { base64_decode, appCategories } from "../views/AppCreator.jsx";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
const SetAuthentication = (props) => {
|
||||
const { globalUrl, serverside } = props;
|
||||
|
||||
const { supportEmail } = useContext(Context);
|
||||
const [app, setApp] = useState({});
|
||||
const [isAppLoaded, setIsAppLoaded] = useState(false);
|
||||
const [loadFail, setLoadFail] = useState("");
|
||||
@@ -114,7 +115,7 @@ const SetAuthentication = (props) => {
|
||||
setLoadFail(
|
||||
<span>
|
||||
<Typography variant="h4">
|
||||
Failed to load the app. Please contact your provider or support@shuffler.io if this persists
|
||||
Failed to load the app. Please contact your provider or {supportEmail} if this persists
|
||||
</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Context } from "../context/ContextApi.jsx"
|
||||
import { ToastContainer, toast } from "react-toastify"
|
||||
import { makeStyles, } from "@mui/styles"
|
||||
import classNames from "classnames"
|
||||
import theme from '../theme.jsx'
|
||||
import {getTheme} from '../theme.jsx'
|
||||
|
||||
import {
|
||||
Autocomplete,
|
||||
@@ -123,7 +123,8 @@ const ParseUsecaseDesc = (priority, appFramework) => {
|
||||
|
||||
const UsecaseListComponent = (props) => {
|
||||
const { keys, userdata, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows, getFramework, setFrameworkData, } = props
|
||||
|
||||
const { themeMode, brandName } = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const [expandedIndex, setExpandedIndex] = useState(-1);
|
||||
const [expandedItem, setExpandedItem] = useState(-1);
|
||||
@@ -199,8 +200,8 @@ const UsecaseListComponent = (props) => {
|
||||
const LoadingSkeleton = () => (
|
||||
<div style={{paddingTop: 75, minHeight: 1000, textAlign: "left"}}>
|
||||
{/* Header skeleton */}
|
||||
<Skeleton variant="text" width={200} height={40} sx={{ bgcolor: 'grey.800' }} />
|
||||
<Skeleton variant="text" width="60%" height={24} sx={{ marginTop: 3, bgcolor: 'grey.800' }} />
|
||||
<Skeleton variant="text" width={200} height={40} />
|
||||
<Skeleton variant="text" width="60%" height={24} sx={{ marginTop: 3, }} />
|
||||
|
||||
{/* Apps selection skeleton */}
|
||||
<Skeleton variant="text" width={150} height={24} sx={{ marginTop: 5, marginBottom: 10 }} />
|
||||
@@ -220,7 +221,7 @@ const UsecaseListComponent = (props) => {
|
||||
variant="circular"
|
||||
width={40}
|
||||
height={40}
|
||||
sx={{ bgcolor: 'grey.800' }}
|
||||
sx={{ bgcolor: theme.palette.loaderColor}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -232,7 +233,7 @@ const UsecaseListComponent = (props) => {
|
||||
sx={{
|
||||
marginTop: "10px",
|
||||
borderRadius: 20,
|
||||
bgcolor: 'grey.800'
|
||||
bgcolor: theme.palette.loaderColor
|
||||
}}
|
||||
/>
|
||||
</Paper>
|
||||
@@ -275,13 +276,13 @@ const UsecaseListComponent = (props) => {
|
||||
variant="circular"
|
||||
width={30}
|
||||
height={30}
|
||||
sx={{ bgcolor: 'grey.800' }}
|
||||
sx={{ bgcolor: theme.palette.loaderColor}}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="circular"
|
||||
width={30}
|
||||
height={30}
|
||||
sx={{ bgcolor: 'grey.800' }}
|
||||
sx={{ bgcolor: theme.palette.loaderColor }}
|
||||
/>
|
||||
</div>
|
||||
{/* Usecase title */}
|
||||
@@ -289,7 +290,7 @@ const UsecaseListComponent = (props) => {
|
||||
variant="text"
|
||||
width="70%"
|
||||
height={24}
|
||||
sx={{ bgcolor: 'grey.800' }}
|
||||
sx={{ bgcolor: theme.palette.loaderColor}}
|
||||
/>
|
||||
</Paper>
|
||||
</Grid>
|
||||
@@ -596,10 +597,10 @@ const UsecaseListComponent = (props) => {
|
||||
|
||||
return (
|
||||
<div style={{paddingTop: 75, minHeight: 1000, textAlign: "left",}}>
|
||||
<Typography variant="h4" style={{color: "white", }}>
|
||||
<b>Usecases</b>
|
||||
<Typography variant="h4" color="textPrimary" style={{fontWeight: "bold"}}>
|
||||
Usecases
|
||||
</Typography>
|
||||
<Typography variant="body1" style={{marginTop: 25, }}>
|
||||
<Typography variant="body1" color="textPrimary" style={{marginTop: 25, }}>
|
||||
Choose a template tailored to your automation requirements, ready for immediate use.
|
||||
</Typography>
|
||||
|
||||
@@ -887,6 +888,9 @@ const Usecases2 = (props) => {
|
||||
const [keys, setKeys] = useState([])
|
||||
const [treeKeys, setTreeKeys] = useState([])
|
||||
|
||||
const { themeMode, brandName } = useContext(Context)
|
||||
const theme = getTheme(themeMode)
|
||||
|
||||
const [selectedUsecaseCategory, setSelectedUsecaseCategory] = useState("");
|
||||
const [selectedUsecases, setSelectedUsecases] = useState([]);
|
||||
const [usecases, setUsecases] = useState([])
|
||||
@@ -987,7 +991,7 @@ const Usecases2 = (props) => {
|
||||
}
|
||||
|
||||
|
||||
document.title = "Shuffle - usecases";
|
||||
document.title = brandName?.length > 0 ? `${brandName} - usecases` : "Shuffle - usecases";
|
||||
var dayGraphLabels = [60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130];
|
||||
var dayGraphData = [60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130];
|
||||
|
||||
|
||||
@@ -440,6 +440,10 @@ export const collapseField = (field, inputdata) => {
|
||||
return true
|
||||
}
|
||||
|
||||
if (field.name === "result") {
|
||||
return false
|
||||
}
|
||||
|
||||
if (field.type === "array") {
|
||||
return true
|
||||
}
|
||||
@@ -454,6 +458,112 @@ export const collapseField = (field, inputdata) => {
|
||||
return false
|
||||
}
|
||||
|
||||
export const HandleJsonCopy = (base, copy, base_node_name) => {
|
||||
if (typeof copy.name === "string") {
|
||||
copy.name = copy.name.replaceAll(" ", "_");
|
||||
}
|
||||
|
||||
//lol
|
||||
if (typeof base === 'object' || typeof base === 'dict') {
|
||||
base = JSON.stringify(base)
|
||||
}
|
||||
|
||||
if (base_node_name === "execution_argument" || base_node_name === "Runtime Argument") {
|
||||
base_node_name = "exec"
|
||||
}
|
||||
|
||||
//console.log("COPY: ", base_node_name, copy);
|
||||
|
||||
//var newitem = JSON.parse(base);
|
||||
var newitem = validateJson(base).result
|
||||
|
||||
var to_be_copied = "$" + base_node_name.toLowerCase().replaceAll(" ", "_");
|
||||
for (let copykey in copy.namespace) {
|
||||
if (copy.namespace[copykey].includes("Results for")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newitem !== undefined && newitem !== null) {
|
||||
newitem = newitem[copy.namespace[copykey]];
|
||||
if (!isNaN(copy.namespace[copykey])) {
|
||||
to_be_copied += ".#";
|
||||
} else {
|
||||
to_be_copied += "." + copy.namespace[copykey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newitem !== undefined && newitem !== null) {
|
||||
newitem = newitem[copy.name];
|
||||
if (!isNaN(copy.name)) {
|
||||
to_be_copied += ".#";
|
||||
} else {
|
||||
to_be_copied += "." + copy.name;
|
||||
}
|
||||
}
|
||||
|
||||
to_be_copied = to_be_copied.replaceAll(" ", "_");
|
||||
console.log("COPY: ", to_be_copied);
|
||||
const elementName = "copy_element_shuffle";
|
||||
var copyText = document.getElementById(elementName);
|
||||
if (copyText !== null && copyText !== undefined) {
|
||||
//console.log("NAVIGATOR: ", navigator);
|
||||
const clipboard = navigator.clipboard;
|
||||
if (clipboard === undefined) {
|
||||
toast("Can only copy over HTTPS (port 3443)");
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(to_be_copied);
|
||||
copyText.select();
|
||||
copyText.setSelectionRange(0, 99999); /* For mobile devices */
|
||||
|
||||
/* Copy the text inside the text field */
|
||||
document.execCommand("copy");
|
||||
//console.log("COPYING!");
|
||||
toast("Copied JSON path to clipboard.")
|
||||
} else {
|
||||
console.log("Couldn't find element ", elementName);
|
||||
}
|
||||
}
|
||||
|
||||
export const handleReactJsonClipboard = (copy) => {
|
||||
const elementName = "copy_element_shuffle";
|
||||
var copyText = document.getElementById(elementName);
|
||||
if (copyText !== null && copyText !== undefined) {
|
||||
if (
|
||||
copy.namespace !== undefined &&
|
||||
copy.name !== undefined &&
|
||||
copy.src !== undefined
|
||||
) {
|
||||
copy = copy.src;
|
||||
}
|
||||
|
||||
const clipboard = navigator.clipboard;
|
||||
if (clipboard === undefined) {
|
||||
toast("Can only copy over HTTPS (port 3443)");
|
||||
return;
|
||||
}
|
||||
|
||||
var stringified = JSON.stringify(copy);
|
||||
if (stringified.startsWith('"') && stringified.endsWith('"')) {
|
||||
stringified = stringified.substring(1, stringified.length - 1);
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(stringified);
|
||||
copyText.select();
|
||||
copyText.setSelectionRange(0, 99999); /* For mobile devices */
|
||||
|
||||
/* Copy the text inside the text field */
|
||||
document.execCommand("copy");
|
||||
|
||||
console.log("COPYING!");
|
||||
toast("Copied value to clipboard, NOT json path.")
|
||||
} else {
|
||||
console.log("Failed to copy from " + elementName + ": ", copyText);
|
||||
}
|
||||
}
|
||||
|
||||
export const validateJson = (showResult) => {
|
||||
if (showResult === undefined || showResult === null) {
|
||||
return {
|
||||
|
||||
+146
-117
@@ -2,7 +2,7 @@
|
||||
import React, { useEffect, useContext, memo, useState, useRef } from "react";
|
||||
import { useLocation, useNavigate, Link } from "react-router-dom";
|
||||
import ReactDOM from "react-dom"
|
||||
|
||||
import { getTheme } from "../theme.jsx";
|
||||
// Material UI Icons
|
||||
import Add from '@mui/icons-material/Add';
|
||||
import Search from '@mui/icons-material/Search';
|
||||
@@ -12,7 +12,6 @@ import GridOnIcon from '@mui/icons-material/GridOn';
|
||||
import ListIcon from '@mui/icons-material/List';
|
||||
import PublishIcon from '@mui/icons-material/Publish';
|
||||
import GetAppIcon from '@mui/icons-material/GetApp';
|
||||
|
||||
// Material UI & Components
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { Navigate } from "react-router-dom";
|
||||
@@ -103,7 +102,7 @@ import Dropzone from "../components/Dropzone.jsx";
|
||||
import { ToastContainer, toast } from "react-toastify"
|
||||
import { MuiChipsInput } from "mui-chips-input";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import theme from "../theme.jsx";
|
||||
// import theme from "./theme.jsx";
|
||||
import algoliasearch from 'algoliasearch/lite';
|
||||
import { InstantSearch, Configure, connectHits, connectSearchBox, connectRefinementList } from 'react-instantsearch-dom';
|
||||
import { debounce } from "lodash";
|
||||
@@ -117,38 +116,7 @@ const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e52
|
||||
const svgSize = 24;
|
||||
const imagesize = 22;
|
||||
|
||||
const useStyles = makeStyles(() => {
|
||||
|
||||
return {
|
||||
datagrid: {
|
||||
border: 0,
|
||||
"& .MuiDataGrid-columnsContainer": {
|
||||
backgroundColor:
|
||||
theme?.palette?.type === "light" ? "#fafafa" : theme?.palette?.inputColor,
|
||||
},
|
||||
"& .MuiDataGrid-iconSeparator": {
|
||||
display: "none",
|
||||
},
|
||||
"& .MuiDataGrid-colCell, .MuiDataGrid-cell": {
|
||||
borderRight: `1px solid ${theme?.palette?.type === "light" ? "white" : "#303030"
|
||||
}`,
|
||||
},
|
||||
"& .MuiDataGrid-columnsContainer, .MuiDataGrid-cell": {
|
||||
borderBottom: `1px solid ${theme?.palette?.type === "light" ? "#f0f0f0" : "#303030"
|
||||
}`,
|
||||
},
|
||||
"& .MuiDataGrid-cell": {
|
||||
color:
|
||||
theme?.palette?.type === "light" ? "white" : "rgba(255,255,255,0.65)",
|
||||
},
|
||||
"& .MuiPaginationItem-root, .MuiTablePagination-actions, .MuiTablePagination-caption":
|
||||
{
|
||||
borderRadius: 0,
|
||||
color: "white",
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -436,19 +404,7 @@ export const GetIconInfo = (action) => {
|
||||
return selectedItem;
|
||||
};
|
||||
|
||||
const chipStyle = {
|
||||
backgroundColor: "#2F2F2F",
|
||||
marginRight: 5,
|
||||
paddingLeft: 5,
|
||||
paddingRight: 5,
|
||||
height: 35,
|
||||
cursor: "pointer",
|
||||
borderColor: "#2F2F2F",
|
||||
color: "#C8C8C8",
|
||||
fontSize: "14px",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
borderRadius: "17.5px"
|
||||
};
|
||||
|
||||
|
||||
export const collapseField = (field) => {
|
||||
if (field === undefined || field === null) {
|
||||
@@ -626,12 +582,14 @@ export const validateJson = (showResult) => {
|
||||
//Custom hook for handling styling of the dropzone
|
||||
const useDropzoneStyles = () => {
|
||||
const { leftSideBarOpenByClick } = useContext(Context);
|
||||
const { themeMode, brandColor } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
return {
|
||||
paddingTop: 70,
|
||||
// minHeight: 1000,
|
||||
backgroundColor: "#1A1A1A",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
// maxWidth: window.innerWidth > 1366 ? 1366 : isMobile ? "100%" : 1200,
|
||||
paddingLeft: leftSideBarOpenByClick ? 200 : 0,
|
||||
transition: "padding-left 0.3s ease",
|
||||
@@ -662,9 +620,59 @@ const Workflows2 = (props) => {
|
||||
const [isLoadingWorkflow, setIsLoadingWorkflow] = useState(false);
|
||||
const [isLoadingPublicWorkflow, setIsLoadingPublicWorkflow] = useState(false);
|
||||
const [view, setView] = useState(localStorage?.getItem("workflowView") || "grid");
|
||||
const classes = useStyles(theme)
|
||||
const imgSize = 60;
|
||||
|
||||
const { themeMode, brandColor, brandName } = useContext(Context);
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
const chipStyle = {
|
||||
backgroundColor: theme.palette.chipStyle.backgroundColor,
|
||||
marginRight: 5,
|
||||
paddingLeft: 5,
|
||||
paddingRight: 5,
|
||||
height: 35,
|
||||
cursor: "pointer",
|
||||
borderColor: theme.palette.chipStyle.borderColor,
|
||||
color: theme.palette.chipStyle.color,
|
||||
fontSize: "14px",
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
borderRadius: "17.5px"
|
||||
};
|
||||
|
||||
const newStyles = makeStyles(() => {
|
||||
|
||||
return {
|
||||
datagrid: {
|
||||
border: 0,
|
||||
"& .MuiDataGrid-columnsContainer": {
|
||||
backgroundColor:
|
||||
theme.palette?.type === "light" ? "#fafafa" : theme.palette?.inputColor,
|
||||
},
|
||||
"& .MuiDataGrid-iconSeparator": {
|
||||
display: "none",
|
||||
},
|
||||
"& .MuiDataGrid-colCell, .MuiDataGrid-cell": {
|
||||
borderRight: `1px solid ${theme.palette?.type === "light" ? "white" : "#303030"
|
||||
}`,
|
||||
},
|
||||
"& .MuiDataGrid-columnsContainer, .MuiDataGrid-cell": {
|
||||
borderBottom: `1px solid ${theme.palette?.type === "light" ? "#f0f0f0" : "#303030"
|
||||
}`,
|
||||
},
|
||||
"& .MuiDataGrid-cell": {
|
||||
color:
|
||||
theme.palette?.type === "light" ? "white" : "rgba(255,255,255,0.65)",
|
||||
},
|
||||
"& .MuiPaginationItem-root, .MuiTablePagination-actions, .MuiTablePagination-caption":
|
||||
{
|
||||
borderRadius: 0,
|
||||
color: "white",
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
const classes = newStyles(theme);
|
||||
|
||||
const referenceUrl = globalUrl + "/api/v1/hooks/";
|
||||
|
||||
var upload = "";
|
||||
@@ -726,7 +734,7 @@ const Workflows2 = (props) => {
|
||||
|
||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||
|
||||
document.title = "Shuffle - Workflows";
|
||||
document.title = brandName?.length > 0 ? `${brandName} - Workflows` : "Shuffle - Workflows";
|
||||
|
||||
useEffect(() => {
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
@@ -1267,6 +1275,19 @@ const Workflows2 = (props) => {
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const queryParams = new URLSearchParams(window.location.search);
|
||||
const paramType = queryParams.get("type");
|
||||
|
||||
if (paramType === "sso_login") {
|
||||
localStorage.removeItem("workflows");
|
||||
queryParams.delete("type");
|
||||
const newUrl = window.location.pathname + (queryParams.toString() ? `?${queryParams.toString()}` : '');
|
||||
|
||||
window.history.replaceState({}, '', newUrl);
|
||||
window.location.reload();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getAvailableWorkflows = (amount) => {
|
||||
var storageWorkflows = []
|
||||
@@ -1568,7 +1589,7 @@ const Workflows2 = (props) => {
|
||||
width: "100%",
|
||||
color: "white",
|
||||
display: "flex",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
boxSizing: "border-box",
|
||||
position: "relative",
|
||||
borderRadius: "8px",
|
||||
@@ -1589,7 +1610,7 @@ const Workflows2 = (props) => {
|
||||
width: 160,
|
||||
height: 44,
|
||||
justifyContent: "space-between",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
};
|
||||
|
||||
const exportAllWorkflows = (allWorkflows) => {
|
||||
@@ -2124,7 +2145,7 @@ const Workflows2 = (props) => {
|
||||
const WorkflowSkeleton = () => {
|
||||
return (
|
||||
<Paper elevation={0} style={{
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
width: "100%",
|
||||
height: 120,
|
||||
borderRadius: 8,
|
||||
@@ -2141,7 +2162,7 @@ const Workflows2 = (props) => {
|
||||
height={90}
|
||||
style={{
|
||||
borderRadius: 6,
|
||||
backgroundColor: "rgba(255, 255, 255, 0.1)"
|
||||
backgroundColor: theme.palette.loaderColor,
|
||||
}}
|
||||
/>
|
||||
<div style={{
|
||||
@@ -2155,19 +2176,19 @@ const Workflows2 = (props) => {
|
||||
variant="text"
|
||||
width="40%"
|
||||
height={24}
|
||||
style={{ backgroundColor: "rgba(255, 255, 255, 0.1)" }}
|
||||
style={{ backgroundColor: theme.palette.loaderColor }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="text"
|
||||
width="60%"
|
||||
height={20}
|
||||
style={{ backgroundColor: "rgba(255, 255, 255, 0.1)" }}
|
||||
style={{ backgroundColor: theme.palette.loaderColor }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="text"
|
||||
width="30%"
|
||||
height={20}
|
||||
style={{ backgroundColor: "rgba(255, 255, 255, 0.1)" }}
|
||||
style={{ backgroundColor: theme.palette.loaderColor }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2240,6 +2261,11 @@ const Workflows2 = (props) => {
|
||||
setOpen(false);
|
||||
setAnchorEl(null);
|
||||
}}
|
||||
MenuListProps={{
|
||||
sx: {
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isDistributed ?
|
||||
<MenuItem
|
||||
@@ -2253,7 +2279,7 @@ const Workflows2 = (props) => {
|
||||
</MenuItem>
|
||||
: null}
|
||||
<MenuItem
|
||||
style={{ backgroundColor: theme.palette.inputColor, color: "white" }}
|
||||
sx={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor, color: theme.palette.text.primary, "&:hover": {backgroundColor: theme.palette.hoverColor} }}
|
||||
disabled={isDistributed}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
@@ -2274,7 +2300,7 @@ const Workflows2 = (props) => {
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
style={{ backgroundColor: theme.palette.inputColor, color: "white" }}
|
||||
sx={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor, color: theme.palette.text.primary, "&:hover": {backgroundColor: theme.palette.hoverColor} }}
|
||||
onClick={(event) => {
|
||||
window.open(`/forms/${data.id}`, "_blank")
|
||||
}}
|
||||
@@ -2287,7 +2313,7 @@ const Workflows2 = (props) => {
|
||||
<Divider />
|
||||
|
||||
<MenuItem
|
||||
style={{ backgroundColor: theme.palette.inputColor, color: "white" }}
|
||||
sx={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor, color: theme.palette.text.primary, "&:hover": {backgroundColor: theme.palette.hoverColor} }}
|
||||
disabled={isDistributed}
|
||||
onClick={() => {
|
||||
sideloadWorkflow(data.id, "publish")
|
||||
@@ -2301,8 +2327,8 @@ const Workflows2 = (props) => {
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
style={{ backgroundColor: theme.palette.inputColor, color: "white" }}
|
||||
disabled={isDistributed}
|
||||
sx={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor, color: theme.palette.text.primary, "&:hover": {backgroundColor: theme.palette.hoverColor} }}
|
||||
//disabled={isDistributed}
|
||||
onClick={() => {
|
||||
sideloadWorkflow(data.id, "export", setOpen)
|
||||
|
||||
@@ -2317,7 +2343,7 @@ const Workflows2 = (props) => {
|
||||
<Divider />
|
||||
|
||||
<MenuItem
|
||||
style={{ backgroundColor: theme.palette.inputColor, color: "white" }}
|
||||
sx={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor, color: theme.palette.text.primary, "&:hover": {backgroundColor: theme.palette.hoverColor} }}
|
||||
disabled={isDistributed}
|
||||
onClick={() => {
|
||||
duplicateWorkflow(data)
|
||||
@@ -2330,7 +2356,7 @@ const Workflows2 = (props) => {
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
style={{ backgroundColor: theme.palette.inputColor, color: "white" }}
|
||||
sx={{ backgroundColor: theme.palette.textFieldStyle.backgroundColor, color: theme.palette.text.primary, "&:hover": {backgroundColor: theme.palette.hoverColor} }}
|
||||
onClick={() => {
|
||||
setDeleteModalOpen(true);
|
||||
setSelectedWorkflowId(data.id);
|
||||
@@ -2447,7 +2473,7 @@ const Workflows2 = (props) => {
|
||||
|
||||
|
||||
return (
|
||||
<div 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 }}>
|
||||
<div 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 }}>
|
||||
<Paper square style={paperAppStyle}>
|
||||
{selectedCategory !== "" ?
|
||||
<Tooltip title={`Usecase Category: ${selectedCategory}`} placement="bottom">
|
||||
@@ -2461,7 +2487,7 @@ const Workflows2 = (props) => {
|
||||
width: 3,
|
||||
backgroundColor: boxColor,
|
||||
borderRadius: "0 100px 0 0",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
}}
|
||||
onClick={() => {
|
||||
addFilter(selectedCategory)
|
||||
@@ -2472,7 +2498,7 @@ const Workflows2 = (props) => {
|
||||
|
||||
<Grid
|
||||
item
|
||||
style={{ display: "flex", flexDirection: "column", width: "100%", fontFamily: theme?.typography?.fontFamily }}
|
||||
style={{ display: "flex", flexDirection: "column", width: "100%", fontFamily: theme.typography?.fontFamily }}
|
||||
>
|
||||
<Grid item style={{ display: "flex", maxHeight: 34 }}>
|
||||
{currTab === 2 ? null :
|
||||
@@ -2526,7 +2552,7 @@ const Workflows2 = (props) => {
|
||||
<Typography style={{
|
||||
color: "rgba(255,255,255,0.9)",
|
||||
fontSize: "16px",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
}}>
|
||||
Edit: {data.name}
|
||||
</Typography>
|
||||
@@ -2553,13 +2579,13 @@ const Workflows2 = (props) => {
|
||||
} placement="right">
|
||||
|
||||
<Typography
|
||||
variant="body1"
|
||||
style={{
|
||||
marginBottom: 0,
|
||||
paddingBottom: 0,
|
||||
fontSize: 18,
|
||||
maxHeight: 30,
|
||||
flex: 10,
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
@@ -2594,7 +2620,7 @@ const Workflows2 = (props) => {
|
||||
style={{
|
||||
height: 24,
|
||||
width: 24,
|
||||
filter: "brightness(0.6)",
|
||||
filter: themeMode === "dark" ? "brightness(0.6)" : "brightness(0.9)",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => {
|
||||
@@ -2751,7 +2777,7 @@ const Workflows2 = (props) => {
|
||||
overflow: "hidden",
|
||||
marginTop: 8,
|
||||
maxHeight: 35,
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
}}
|
||||
>
|
||||
{data.tags !== undefined && data.tags !== null
|
||||
@@ -3395,7 +3421,7 @@ const Workflows2 = (props) => {
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div style={{ ...gridContainer, backgroundColor: "#212121" }}>
|
||||
<div style={{ ...gridContainer, backgroundColor: theme.palette.platformColor }}>
|
||||
<Tooltip title={`New Workflow`} placement="bottom">
|
||||
<IconButton
|
||||
style={{ position: "absolute", top: 10, right: 50, zIndex: 1000 }}
|
||||
@@ -3984,8 +4010,8 @@ const Workflows2 = (props) => {
|
||||
|
||||
|
||||
const iconButtonStyle = {
|
||||
color: 'white',
|
||||
backgroundColor: '#212121',
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
borderRadius: '4px',
|
||||
padding: "12px 16px",
|
||||
cursor: 'pointer',
|
||||
@@ -4085,20 +4111,20 @@ const Workflows2 = (props) => {
|
||||
maxWidth: "25%",
|
||||
minWidth: "25%",
|
||||
height: 47,
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
height: "100%",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
},
|
||||
placeholder: "Search Workflows",
|
||||
}}
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
borderRadius: '4px',
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
},
|
||||
}}
|
||||
value={localQuery}
|
||||
@@ -4140,9 +4166,9 @@ const Workflows2 = (props) => {
|
||||
maxWidth: "25%",
|
||||
height: 47,
|
||||
borderRadius: 4,
|
||||
backgroundColor: "#212121",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
color: "#FFFFFF",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
}}
|
||||
MenuProps={{
|
||||
anchorOrigin: {
|
||||
@@ -4155,9 +4181,9 @@ const Workflows2 = (props) => {
|
||||
},
|
||||
PaperProps: {
|
||||
style: {
|
||||
backgroundColor: '#212121',
|
||||
color: '#FFFFFF',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -4193,7 +4219,7 @@ const Workflows2 = (props) => {
|
||||
)
|
||||
}
|
||||
>
|
||||
<MenuItem disabled value="" style={{ fontFamily: theme?.typography?.fontFamily, fontSize: 16 }}>
|
||||
<MenuItem disabled value="" style={{ fontFamily: theme.typography?.fontFamily, fontSize: 16 }}>
|
||||
All Usecases
|
||||
</MenuItem>
|
||||
{items.map((usecase, index) => (
|
||||
@@ -4206,13 +4232,13 @@ const Workflows2 = (props) => {
|
||||
'&:hover': {
|
||||
backgroundColor: '#3A3A3A', // Darker background on hover
|
||||
},
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
fontSize: 16
|
||||
}}
|
||||
>
|
||||
<Checkbox
|
||||
checked={currentRefinement.includes(usecase.label)}
|
||||
style={{ marginRight: 8, color: '#FFFFFF', fontSize: 16 }}
|
||||
style={{ marginRight: 8, fontSize: 16 }}
|
||||
/>
|
||||
{usecase.label} ({usecase.count})
|
||||
</MenuItem>
|
||||
@@ -4225,7 +4251,7 @@ const Workflows2 = (props) => {
|
||||
const tabStyle = {
|
||||
textTransform: 'none',
|
||||
marginRight: 20,
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
fontSize: 16,
|
||||
borderBottom: "5px solid transparent",
|
||||
minHeight: "48px",
|
||||
@@ -4233,9 +4259,9 @@ const Workflows2 = (props) => {
|
||||
}
|
||||
|
||||
const tabActive = {
|
||||
borderBottom: "5px solid #FF8544",
|
||||
borderBottom: `5px solid ${theme.palette.primary.main}`,
|
||||
borderRadius: "2px",
|
||||
color: "#FF8544"
|
||||
color: theme.palette.primary.main
|
||||
}
|
||||
|
||||
|
||||
@@ -4258,16 +4284,16 @@ const Workflows2 = (props) => {
|
||||
maxWidth: isSafari ? "100%" : "70%",
|
||||
margin: "auto",
|
||||
}}>
|
||||
<Typography variant="h4" style={{ marginBottom: 20, paddingLeft: 15, textTransform: 'none', fontFamily: theme?.typography?.fontFamily }}>
|
||||
<Typography variant="h4" color="textPrimary" style={{ marginBottom: 20, paddingLeft: 15, textTransform: 'none', fontFamily: theme.typography?.fontFamily }}>
|
||||
{currTab === 0 ? "Org" : currTab === 1 ? "Your" : "Discover"} Workflows
|
||||
</Typography>
|
||||
|
||||
<div style={{ borderBottom: '1px solid gray', marginBottom: 30 }}>
|
||||
<div style={{ borderBottom: themeMode === "dark" ? "1px solid #808080" : theme.palette.defaultBorder, marginBottom: 30 }}>
|
||||
<Tabs
|
||||
value={currTab}
|
||||
onChange={(event, newTab) => handleTabChange(event, newTab)}
|
||||
style={{
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
fontSize: 16,
|
||||
marginBottom: "-2px"
|
||||
}}
|
||||
@@ -4327,16 +4353,17 @@ const Workflows2 = (props) => {
|
||||
minWidth: "25%",
|
||||
height: 43,
|
||||
maxHeight: "fit-content",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
zIndex: 1000,
|
||||
color: theme.palette.textFieldStyle.color
|
||||
}}
|
||||
disabled={currTab === 2}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
height: "fit-content",
|
||||
maxHeight: "fit-content",
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color
|
||||
},
|
||||
placeholder: "Filter Workflows",
|
||||
// endAdornment: (
|
||||
@@ -4359,7 +4386,8 @@ const Workflows2 = (props) => {
|
||||
'& .MuiOutlinedInput-root': {
|
||||
height: "fit-content",
|
||||
borderRadius: '4px',
|
||||
backgroundColor: '#212121',
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
'& fieldset': {
|
||||
borderColor: 'rgba(255, 255, 255, 0.23)',
|
||||
},
|
||||
@@ -4373,10 +4401,12 @@ const Workflows2 = (props) => {
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
gap: '4px',
|
||||
fontSize: 18,
|
||||
padding: '4px 8px',
|
||||
alignItems: 'center',
|
||||
height: "fit-content", // Match height
|
||||
backgroundColor: "#212121",
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
color: theme.palette.textFieldStyle.color
|
||||
},
|
||||
|
||||
// Rest of the styling remains the same...
|
||||
@@ -4424,8 +4454,9 @@ const Workflows2 = (props) => {
|
||||
maxWidth: "25%",
|
||||
height: 47,
|
||||
borderRadius: 4,
|
||||
backgroundColor: "#212121",
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
fontSize: 18,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
}}
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
@@ -4460,12 +4491,12 @@ const Workflows2 = (props) => {
|
||||
removeFilter(filters.indexOf(usecase?.name.toLowerCase()))
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
sx={{
|
||||
padding: "12px 16px",
|
||||
borderBottom: index === usecases.length - 2 ? "none" : "1px solid rgba(255,255,255,0.05)",
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(255,255,255,0.1)"
|
||||
}
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
@@ -4479,7 +4510,7 @@ const Workflows2 = (props) => {
|
||||
style={{
|
||||
padding: 0,
|
||||
marginRight: 8,
|
||||
color: "rgba(255,255,255,0.7)"
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
}}
|
||||
/>
|
||||
<div style={{
|
||||
@@ -4491,7 +4522,7 @@ const Workflows2 = (props) => {
|
||||
<Typography
|
||||
variant="body1"
|
||||
style={{
|
||||
color: "rgba(255,255,255,0.9)",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
fontWeight: selectedCategory.includes(category) ? 500 : 400
|
||||
}}
|
||||
>
|
||||
@@ -4500,8 +4531,8 @@ const Workflows2 = (props) => {
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{
|
||||
color: "rgba(255,255,255,0.5)",
|
||||
backgroundColor: "rgba(255,255,255,0.1)",
|
||||
color: theme.palette.textFieldStyle.color,
|
||||
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||
padding: "2px 8px",
|
||||
borderRadius: "12px",
|
||||
fontSize: "0.75rem"
|
||||
@@ -4539,7 +4570,7 @@ const Workflows2 = (props) => {
|
||||
onClick={() => navigate("/workflows/debug")}
|
||||
disabled={currTab === 2}
|
||||
>
|
||||
<QueryStatsIcon style={{ color: currTab === 2 ? "rgba(241, 241, 241, 0.5)" : "#F1F1F1" }} />
|
||||
<QueryStatsIcon style={{ color: theme.palette.text.primary, opacity: currTab === 2 ? 0.5 : 1 }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
@@ -4554,8 +4585,8 @@ const Workflows2 = (props) => {
|
||||
disabled={currTab === 2}
|
||||
>
|
||||
{view === "grid" ?
|
||||
<ListIcon style={{ color: currTab === 2 ? "rgba(255, 255, 255, 0.5)" : "white" }} /> :
|
||||
<GridOnIcon style={{ color: currTab === 2 ? "rgba(255, 255, 255, 0.5)" : "white" }} />
|
||||
<ListIcon style={{ color: theme.palette.text.primary, opacity: currTab === 2 ? 0.5 : 1 }} /> :
|
||||
<GridOnIcon style={{ color: theme.palette.text.primary, opacity: currTab === 2 ? 0.5 : 1 }} />
|
||||
}
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
@@ -4568,7 +4599,7 @@ const Workflows2 = (props) => {
|
||||
>
|
||||
{submitLoading ?
|
||||
<CircularProgress color="secondary" /> :
|
||||
<PublishIcon style={{ color: currTab === 2 ? "rgba(255, 255, 255, 0.5)" : "white" }} />
|
||||
<PublishIcon style={{ color: theme.palette.text.primary, opacity: currTab === 2 ? 0.5 : 1}} />
|
||||
}
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
@@ -4587,7 +4618,7 @@ const Workflows2 = (props) => {
|
||||
disabled={isCloud || currTab === 2}
|
||||
onClick={() => exportAllWorkflows(workflows)}
|
||||
>
|
||||
<GetAppIcon style={{ color: (isCloud || currTab === 2) ? "rgba(255, 255, 255, 0.5)" : "white" }} />
|
||||
<GetAppIcon style={{ color: theme.palette.text.primary, opacity: currTab === 2 ? 0.5 : 1}} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
@@ -4600,13 +4631,11 @@ const Workflows2 = (props) => {
|
||||
borderRadius: 4,
|
||||
flex: 0.8,
|
||||
textTransform: 'none',
|
||||
backgroundColor: "#FF8544",
|
||||
color: "#1A1A1A",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontFamily: theme.typography?.fontFamily,
|
||||
fontSize: 16,
|
||||
fontWeight: 500
|
||||
}}
|
||||
startIcon={<Add style={{ color: "#1A1A1A" }} />}
|
||||
startIcon={<Add/>}
|
||||
>
|
||||
Create Workflow
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user