Loads of more bugfixes and tests

This commit is contained in:
frikky
2023-01-24 03:24:55 +01:00
parent 4e7f26126b
commit ef045bc5bd
13 changed files with 1529 additions and 962 deletions
+316 -331
View File
@@ -72,9 +72,11 @@ import {
} from "@material-ui/icons";
import { useAlert } from "react-alert";
import Dropzone from "../components/Dropzone";
import HandlePaymentNew from "./HandlePaymentNew";
import Dropzone from "../components/Dropzone.jsx";
import HandlePaymentNew from "../views/HandlePaymentNew.jsx";
import OrgHeader from "../components/OrgHeader.jsx";
import OrgHeaderexpanded from "../components/OrgHeaderexpanded.jsx";
import Billing from "../components/Billing.jsx";
import { display, style } from "@mui/system";
const useStyles = makeStyles({
@@ -188,8 +190,10 @@ const Admin = (props) => {
const [dealDiscount, setDealDiscount] = React.useState("");
const [dealerror, setDealerror] = React.useState("");
const [dealList, setDealList] = React.useState([]);
const [adminTab, setAdminTab] = React.useState(1);
const [fileContent, setFileContent] = React.useState("");
const [billingInfo, setBillingInfo] = React.useState({});
useEffect(() => {
if (isDropzone) {
@@ -1562,6 +1566,14 @@ const Admin = (props) => {
5: "environments",
6: "suborgs",
};
const admin_views = {
0: "organization",
1: "cloud_sync",
2: "billing",
3: "stats",
};
const setConfig = (event, inputValue) => {
const newValue = parseInt(inputValue);
@@ -1612,17 +1624,29 @@ const Admin = (props) => {
) {
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
const foundTab = params["tab"];
if (foundTab !== null && foundTab !== undefined) {
for (var key in Object.keys(views)) {
const value = views[key];
console.log(key, value);
if (value === foundTab) {
setConfig("", key);
const adminTab = params["admin_tab"];
if (adminTab !== null && adminTab !== undefined) {
for (var key in Object.keys(admin_views)) {
const value = admin_views[key];
if (value === adminTab) {
setAdminTab(parseInt(key));
setConfig("", 0);
break;
}
}
}
} else {
const foundTab = params["tab"];
if (foundTab !== null && foundTab !== undefined) {
for (var key in Object.keys(views)) {
const value = views[key];
if (value === foundTab) {
setConfig("", key);
break;
}
}
}
}
}
}
@@ -2612,48 +2636,7 @@ const Admin = (props) => {
});
};
const cancelSubscriptions = (subscription_id) => {
console.log(selectedOrganization);
const orgId = selectedOrganization.id;
const data = {
subscription_id: subscription_id,
action: "cancel",
org_id: selectedOrganization.id,
};
const url = globalUrl + `/api/v1/orgs/${orgId}`;
fetch(url, {
mode: "cors",
method: "POST",
body: JSON.stringify(data),
credentials: "include",
crossDomain: true,
withCredentials: true,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
})
.then(function (response) {
if (response.status !== 200) {
console.log("Error in response");
}
handleGetOrg(selectedOrganization.id);
return response.json();
})
.then(function (responseJson) {
if (responseJson.success !== undefined && responseJson.success) {
alert.success("Successfully stopped subscription!");
} else {
alert.error("Failed stopping subscription. Please contact us.");
}
})
.catch(function (error) {
console.log("Error: ", error);
alert.error("Failed stopping subscription. Please contact us.");
});
};
const organizationView =
curTab === 0 && selectedOrganization.id !== undefined ? (
<div style={{ position: "relative" }}>
@@ -2758,6 +2741,7 @@ const Admin = (props) => {
setSelectedOrganization={setSelectedOrganization}
globalUrl={globalUrl}
selectedOrganization={selectedOrganization}
adminTab={adminTab}
/>
) : (
<div
@@ -2772,6 +2756,51 @@ const Admin = (props) => {
<Typography>Loading Organization</Typography>
</div>
)}
<Tabs
value={adminTab}
indicatorColor="primary"
textColor="secondary"
style={{marginTop: 20, }}
onChange={(event, inputValue) => {
const newValue = parseInt(inputValue);
setAdminTab(newValue);
//const setConfig = (event, inputValue) => {
navigate(`/admin?admin_tab=${admin_views[newValue]}`);
}}
aria-label="disabled tabs example"
>
<Tab
label=<span>
Edit Details
</span>
/>
<Tab
label=<span>
Cloud Synchronization
</span>
/>
<Tab
disabled={!isCloud}
label=<span>
Billing
</span>
/>
<Tab
disabled={true}
label=<span>
Usage
</span>
/>
<Tab
disabled={true}
label=<span>
Notifications
</span>
/>
</Tabs>
<Divider
style={{
marginTop: 20,
@@ -2779,205 +2808,241 @@ const Admin = (props) => {
backgroundColor: theme.palette.inputColor,
}}
/>
<Typography
variant="h6"
style={{ marginBottom: "10px", color: "white" }}
>
Cloud syncronization
</Typography>
What does{" "}
<a
href="https://shuffler.io/docs/organizations#cloud_sync"
target="_blank"
rel="noopener noreferrer"
style={{ textDecoration: "none", color: "#f85a3e" }}
>
cloud sync
</a>{" "}
do? Cloud syncronization is a way of getting more out of Shuffle.
Shuffle will <b>ALWAYS</b> make every option open source, but
features relying on other users can't be done without a
collaborative approach.
{isCloud ? (
<div style={{ marginTop: 15, display: "flex" }}>
<div style={{ flex: 1 }}>
<Typography style={{}}>
Currently syncronizing:{" "}
{selectedOrganization.cloud_sync_active === true
? "True"
: "False"}
</Typography>
{selectedOrganization.cloud_sync_active ? (
<Typography style={{}}>
Syncronization interval:{" "}
{selectedOrganization.sync_config.interval === 0
? "60"
: selectedOrganization.sync_config.interval}
</Typography>
) : null}
<Typography
style={{
whiteSpace: "nowrap",
marginTop: 25,
marginRight: 10,
}}
>
Your Apikey
</Typography>
<div style={{ display: "flex" }}>
<TextField
color="primary"
style={{ backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
height: "50px",
color: "white",
fontSize: "1em",
},
}}
required
fullWidth={true}
disabled={true}
autoComplete="cloud apikey"
id="apikey_field"
margin="normal"
placeholder="Cloud Apikey"
variant="outlined"
defaultValue={userSettings.apikey}
/>
{selectedOrganization.cloud_sync_active ? (
<Button
style={{
width: 150,
height: 50,
marginLeft: 10,
marginTop: 17,
}}
variant={
selectedOrganization.cloud_sync_active === true
? "outlined"
: "contained"
}
color="primary"
onClick={() => {
handleStopOrgSync(selectedOrganization.id);
}}
>
Stop Sync
</Button>
) : null}
</div>
</div>
</div>
) : (
<div>
<div style={{ display: "flex", marginBottom: 20 }}>
<TextField
color="primary"
style={{
backgroundColor: theme.palette.inputColor,
marginRight: 10,
}}
InputProps={{
style: {
height: "50px",
color: "white",
fontSize: "1em",
},
}}
required
fullWidth={true}
disabled={selectedOrganization.cloud_sync}
autoComplete="cloud apikey"
id="apikey_field"
margin="normal"
placeholder="Cloud Apikey"
variant="outlined"
onChange={(event) => {
setCloudSyncApikey(event.target.value);
}}
/>
<Button
disabled={
(!selectedOrganization.cloud_sync &&
cloudSyncApikey.length === 0) ||
loading
}
style={{ marginTop: 15, height: 50, width: 150 }}
onClick={() => {
setLoading(true);
enableCloudSync(
cloudSyncApikey,
selectedOrganization,
selectedOrganization.cloud_sync
);
}}
color="primary"
variant={
selectedOrganization.cloud_sync === true
? "outlined"
: "contained"
}
>
{selectedOrganization.cloud_sync
? "Stop sync"
: "Start sync"}
</Button>
</div>
{orgSyncResponse.length > 0 ? (
<Typography style={{ marginTop: 5, marginBottom: 10 }}>
Message from Shuffle Cloud: <b>{orgSyncResponse}</b>
</Typography>
) : null}
</div>
)}
<Typography
style={{ marginTop: 40, marginLeft: 10, marginBottom: 5 }}
>
Cloud sync features (monthly usage)
</Typography>
<Grid container style={{ width: "100%", marginBottom: 15 }}>
{selectedOrganization.sync_features === undefined ||
selectedOrganization.sync_features === null
? null
: Object.keys(selectedOrganization.sync_features).map(function (
key,
index
) {
// unnecessary parts
if (key === "schedule" || key === "apps" || key === "updates") {
return null;
}
const item = selectedOrganization.sync_features[key];
if (item === null) {
return null
}
{adminTab === 0 ? (
<OrgHeaderexpanded
isCloud={isCloud}
userdata={userdata}
setSelectedOrganization={setSelectedOrganization}
globalUrl={globalUrl}
selectedOrganization={selectedOrganization}
adminTab={adminTab}
/>
)
: adminTab === 1 ? (
<div>
<Typography
variant="h6"
style={{ marginBottom: "10px", color: "white" }}
>
Cloud syncronization
</Typography>
What does{" "}
<a
href="https://shuffler.io/docs/organizations#cloud_sync"
target="_blank"
rel="noopener noreferrer"
style={{ textDecoration: "none", color: "#f85a3e" }}
>
cloud sync
</a>{" "}
do? Cloud syncronization is a way of getting more out of Shuffle.
Shuffle will <b>ALWAYS</b> make every option open source, but
features relying on other users can't be done without a
collaborative approach.
{isCloud ? (
<div style={{ marginTop: 15, display: "flex" }}>
<div style={{ flex: 1 }}>
<Typography style={{}}>
Currently syncronizing:{" "}
{selectedOrganization.cloud_sync_active === true
? "True"
: "False"}
</Typography>
{selectedOrganization.cloud_sync_active ? (
<Typography style={{}}>
Syncronization interval:{" "}
{selectedOrganization.sync_config.interval === 0
? "60"
: selectedOrganization.sync_config.interval}
</Typography>
) : null}
<Typography
style={{
whiteSpace: "nowrap",
marginTop: 25,
marginRight: 10,
}}
>
Your Apikey
</Typography>
<div style={{ display: "flex" }}>
<TextField
color="primary"
style={{ backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
height: "50px",
color: "white",
fontSize: "1em",
},
}}
required
fullWidth={true}
disabled={true}
autoComplete="cloud apikey"
id="apikey_field"
margin="normal"
placeholder="Cloud Apikey"
variant="outlined"
defaultValue={userSettings.apikey}
/>
{selectedOrganization.cloud_sync_active ? (
<Button
style={{
width: 150,
height: 50,
marginLeft: 10,
marginTop: 17,
}}
variant={
selectedOrganization.cloud_sync_active === true
? "outlined"
: "contained"
}
color="primary"
onClick={() => {
handleStopOrgSync(selectedOrganization.id);
}}
>
Stop Sync
</Button>
) : null}
</div>
</div>
</div>
) : (
<div>
<div style={{ display: "flex", marginBottom: 20 }}>
<TextField
color="primary"
style={{
backgroundColor: theme.palette.inputColor,
marginRight: 10,
}}
InputProps={{
style: {
height: "50px",
color: "white",
fontSize: "1em",
},
}}
required
fullWidth={true}
disabled={selectedOrganization.cloud_sync}
autoComplete="cloud apikey"
id="apikey_field"
margin="normal"
placeholder="Cloud Apikey"
variant="outlined"
onChange={(event) => {
setCloudSyncApikey(event.target.value);
}}
/>
<Button
disabled={
(!selectedOrganization.cloud_sync &&
cloudSyncApikey.length === 0) ||
loading
}
style={{ marginTop: 15, height: 50, width: 150 }}
onClick={() => {
setLoading(true);
enableCloudSync(
cloudSyncApikey,
selectedOrganization,
selectedOrganization.cloud_sync
);
}}
color="primary"
variant={
selectedOrganization.cloud_sync === true
? "outlined"
: "contained"
}
>
{selectedOrganization.cloud_sync
? "Stop sync"
: "Start sync"}
</Button>
</div>
{orgSyncResponse.length > 0 ? (
<Typography style={{ marginTop: 5, marginBottom: 10 }}>
Message from Shuffle Cloud: <b>{orgSyncResponse}</b>
</Typography>
) : null}
</div>
)}
<Typography
style={{ marginTop: 40, marginLeft: 10, marginBottom: 5 }}
>
Cloud sync features (monthly usage)
</Typography>
<Grid container style={{ width: "100%", marginBottom: 15 }}>
{selectedOrganization.sync_features === undefined ||
selectedOrganization.sync_features === null
? null
: Object.keys(selectedOrganization.sync_features).map(function (
key,
index
) {
// unnecessary parts
if (key === "schedule" || key === "apps" || key === "updates") {
return null;
}
const newkey = key.replaceAll("_", " ");
const griditem = {
primary: newkey,
secondary:
item.description === undefined ||
item.description === null ||
item.description.length === 0
? "Not defined yet"
: item.description,
limit: item.limit,
usage: item.usage === undefined ||
item.usage === null ? 0 : item.usage,
data_collection: "None",
active: item.active,
icon: <PolymerIcon style={{ color: itemColor }} />,
};
const item = selectedOrganization.sync_features[key];
if (item === null) {
return null
}
return (
<Zoom key={index}>
<GridItem data={griditem} />
</Zoom>
);
})}
</Grid>
const newkey = key.replaceAll("_", " ");
const griditem = {
primary: newkey,
secondary:
item.description === undefined ||
item.description === null ||
item.description.length === 0
? "Not defined yet"
: item.description,
limit: item.limit,
usage: item.usage === undefined ||
item.usage === null ? 0 : item.usage,
data_collection: "None",
active: item.active,
icon: <PolymerIcon style={{ color: itemColor }} />,
};
return (
<Zoom key={index}>
<GridItem data={griditem} />
</Zoom>
);
})}
</Grid>
</div>
)
: adminTab === 2 ?
<Billing
isCloud={isCloud}
userdata={userdata}
setSelectedOrganization={setSelectedOrganization}
globalUrl={globalUrl}
selectedOrganization={selectedOrganization}
adminTab={adminTab}
billingInfo={billingInfo}
selectedOrganization={selectedOrganization}
stripeKey={props.stripeKey}
handleGetOrg={handleGetOrg}
/>
: adminTab === 3 ?
<div>
<Typography style={{ marginTop: 20, marginBottom: 10 }}>
Stats
</Typography>
</div>
: null
}
<Divider
style={{
marginTop: 20,
@@ -2986,8 +3051,8 @@ const Admin = (props) => {
}}
/>
{isCloud &&
selectedOrganization.partner_info !== undefined &&
selectedOrganization.partner_info.reseller === true ? (
selectedOrganization.partner_info !== undefined &&
selectedOrganization.partner_info.reseller === true ? (
<div style={{ marginTop: 30, marginBottom: 200 }}>
<Typography
style={{ marginTop: 40, marginLeft: 10, marginBottom: 5 }}
@@ -3169,89 +3234,9 @@ const Admin = (props) => {
/>
</div>
) : null}
{isCloud &&
selectedOrganization.subscriptions !== undefined &&
selectedOrganization.subscriptions !== null &&
selectedOrganization.subscriptions.length > 0 ? (
<div style={{ marginTop: 30, marginBottom: 20 }}>
<Typography
style={{ marginTop: 40, marginLeft: 10, marginBottom: 5 }}
>
Your subscription
{selectedOrganization.subscriptions.length > 1 ? "s" : ""}
</Typography>
<Grid container spacing={3} style={{ marginTop: 15 }}>
{selectedOrganization.subscriptions
.reverse()
.map((sub, index) => {
return (
<Grid item key={index} xs={4}>
<Card
elevation={6}
style={{
backgroundColor: theme.palette.inputColor,
color: "white",
padding: 25,
textAlign: "left",
}}
>
<b>Type</b>: {sub.level}
<div />
<b>Recurrence</b>: {sub.recurrence}
<div />
{sub.active ? (
<div>
<b>Started</b>:{" "}
{new Date(sub.startdate * 1000).toISOString()}
<div />
<Button
variant="outlined"
color="primary"
style={{ marginTop: 15 }}
onClick={() => {
cancelSubscriptions(sub.reference);
}}
>
Cancel subscription
</Button>
</div>
) : (
<div>
<b>Cancelled</b>:{" "}
{new Date(
sub.cancellationdate * 1000
).toISOString()}
<div />
<Typography color="textSecondary">
<b>Status</b>: Deactivated
</Typography>
</div>
)}
</Card>
</Grid>
);
})}
</Grid>
<Divider
style={{
marginTop: 20,
backgroundColor: theme.palette.inputColor,
}}
/>
</div>
) : null}
</div>
)}
<div style={{ backgroundColor: "#1f2023", paddingTop: 25 }}>
<HandlePaymentNew
theme={theme}
stripeKey={props.stripeKey}
userdata={userdata}
globalUrl={globalUrl}
{...props}
/>
</div>
</div>
) : null;
-1
View File
@@ -6144,7 +6144,6 @@ const AngularWorkflow = (defaultprops) => {
const [hover, setHover] = React.useState(false);
if (app.id === "" || app.name === "") {
console.log("Skipping app: ", app)
return null
}
+306 -17
View File
@@ -26,6 +26,12 @@ import {
DialogContent,
CircularProgress,
Zoom,
InputAdornment,
List,
ListItem,
ListItemAvatar,
ListItemText,
Avatar,
} from "@material-ui/core";
import {
@@ -37,18 +43,24 @@ import {
CloudDownload as CloudDownloadIcon,
Edit as EditIcon,
Delete as DeleteIcon,
Search as SearchIcon,
Folder as FolderIcon,
LibraryBooks as LibraryBooksIcon,
} from "@material-ui/icons";
import {
ForkRight as ForkRightIcon,
} from '@mui/icons-material';
import aa from 'search-insights'
import { useTheme } from "@material-ui/core/styles";
import { InstantSearch, Configure, connectSearchBox, connectHits, Index } from 'react-instantsearch-dom';
import algoliasearch from 'algoliasearch/lite';
import YAML from "yaml";
import { useNavigate, Link, useParams } from "react-router-dom";
import { useAlert } from "react-alert";
import Dropzone from "../components/Dropzone";
import Dropzone from "../components/Dropzone.jsx";
const surfaceColor = "#27292D";
const inputColor = "#383B40";
@@ -254,6 +266,7 @@ export const GetParsedPaths = (inputdata, basekey) => {
return parsedValues;
};
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240")
const Apps = (props) => {
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
@@ -1486,6 +1499,268 @@ const Apps = (props) => {
}, [appValidation, isDropzone]);
var appDelay = -75
const leftBarSize = viewWidth
const SearchBox = ({ currentRefinement, refine, isSearchStalled, }) => {
useEffect(() => {
if (document !== undefined) {
const appsearchValue = document.getElementById("app_search_field")
if (appsearchValue !== undefined && appsearchValue !== null) {
console.log("Value2: ", appsearchValue.value)
if (appsearchValue.value !== undefined && appsearchValue.value !== null && appsearchValue.value.length > 0) {
refine(appsearchValue.value)
}
}
//}
}
}, [])
return (
<form id="search_form" noValidate type="searchbox" action="" role="search" style={{ margin: 0, display: "none", }} onClick={() => {
}}>
<TextField
fullWidth
style={{ backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius, maxWidth: leftBarSize - 20, }}
InputProps={{
style: {
color: "white",
fontSize: "1em",
height: 50,
margin: 0,
},
startAdornment: (
<InputAdornment position="start">
<SearchIcon style={{ marginLeft: 5 }} />
</InputAdornment>
),
}}
autoComplete='off'
type="search"
color="primary"
placeholder="Find Public Apps, Workflows, Documentation and more"
value={currentRefinement}
id="shuffle_search_field"
onClick={(event) => {
console.log("Click!")
}}
onBlur={(event) => {
//setSearchOpen(false)
}}
onChange={(event) => {
//if (event.currentTarget.value.length > 0 && !searchOpen) {
// setSearchOpen(true)
//}
refine(event.currentTarget.value)
}}
limit={5}
/>
{/*isSearchStalled ? 'My search is stalled' : ''*/}
</form>
)
}
const activateApp = (appid, refresh) => {
fetch(globalUrl + "/api/v1/apps/" + appid + "/activate", {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Failed to activate")
}
return response.json()
})
.then((responseJson) => {
if (responseJson.success === false) {
alert.error("Failed to activate the app")
} else {
alert.success("App activated for your organization! Refresh the page to use the app.")
if (refresh === true) {
getApps()
}
}
})
.catch(error => {
//alert.error(error.toString())
console.log("Activate app error: ", error.toString())
});
}
const AppHits = ({ hits }) => {
const [mouseHoverIndex, setMouseHoverIndex] = React.useState(0)
//var tmp = searchOpen
//if (!searchOpen) {
// return null
//}
const positionInfo = document.activeElement.getBoundingClientRect()
const outerlistitemStyle = {
width: "100%",
overflowX: "hidden",
overflowY: "hidden",
borderBottom: "1px solid rgba(255,255,255,0.4)",
}
if (hits.length > 4) {
hits = hits.slice(0, 4)
}
var type = "app"
const baseImage = <LibraryBooksIcon />
return (
<div style={{ position: "relative", marginTop: 15, marginLeft: 0, marginRight: 10, position: "absolute", color: "white", zIndex: 1001, backgroundColor: theme.palette.inputColor, minWidth: leftBarSize - 10, maxWidth: leftBarSize - 10, boxShadows: "none", overflowX: "hidden", }}>
<List style={{ backgroundColor: theme.palette.inputColor, }}>
{hits.length === 0 ?
<ListItem style={outerlistitemStyle}>
<ListItemAvatar onClick={() => console.log(hits)}>
<Avatar>
<FolderIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={"No public apps found."}
secondary={"Try a broader search term"}
/>
</ListItem>
:
hits.map((hit, index) => {
const innerlistitemStyle = {
width: positionInfo.width + 35,
overflowX: "hidden",
overflowY: "hidden",
borderBottom: "1px solid rgba(255,255,255,0.4)",
backgroundColor: mouseHoverIndex === index ? "#1f2023" : "inherit",
cursor: "pointer",
marginLeft: 0,
marginRight: 0,
maxHeight: 75,
minHeight: 75,
maxWidth: 420,
minWidth: "100%",
}
const name = hit.name === undefined ?
hit.filename.charAt(0).toUpperCase() + hit.filename.slice(1).replaceAll("_", " ") + " - " + hit.title :
(hit.name.charAt(0).toUpperCase() + hit.name.slice(1)).replaceAll("_", " ")
var secondaryText = hit.data !== undefined ? hit.data.slice(0, 40) + "..." : ""
const avatar = hit.image_url === undefined ?
baseImage
:
<Avatar
src={hit.image_url}
variant="rounded"
/>
//console.log(hit)
if (hit.categories !== undefined && hit.categories !== null && hit.categories.length > 0) {
secondaryText = hit.categories.slice(0, 3).map((data, index) => {
if (index === 0) {
return data
}
return ", " + data
/*
<Chip
key={index}
style={chipStyle}
label={data}
onClick={() => {
//handleChipClick
}}
variant="outlined"
color="primary"
/>
*/
})
}
var parsedUrl = isCloud ? `/apps/${hit.objectID}` : `https://shuffler.io/apps/${hit.objectID}`
parsedUrl += `?queryID=${hit.__queryID}`
return (
<div style={{ textDecoration: "none", color: "white", }} onClick={(event) => {
//if (!isCloud) {
// alert.info("Since this is an on-prem instance. You will need to activate the app yourself. Opening link to download it in a new window.")
// setTimeout(() => {
// event.preventDefault()
// window.open(parsedUrl, '_blank')
// }, 2000)
//} else {
alert.info(`Activating ${name}`)
//}
console.log("CLICK: ", hit)
const queryID = hit.__queryID
console.log("QUERY: ", queryID)
if (queryID !== undefined && queryID !== null) {
aa('init', {
appId: "JNSS5CFDZZ",
apiKey: "db08e40265e2941b9a7d8f644b6e5240",
})
const timestamp = new Date().getTime()
aa('sendEvents', [
{
eventType: 'conversion',
eventName: 'Public App Activated',
index: 'appsearch',
objectIDs: [hit.objectID],
timestamp: timestamp,
queryID: queryID,
userToken: userdata === undefined || userdata === null || userdata.id === undefined ? "unauthenticated" : userdata.id,
}
])
} else {
console.log("No query to handle when activating")
}
activateApp(hit.objectID, true)
}}>
<ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => {
setMouseHoverIndex(index)
}}>
<ListItemAvatar>
{avatar}
</ListItemAvatar>
<ListItemText
primary={name}
secondary={secondaryText}
/>
{/*
<ListItemSecondaryAction>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
*/}
</ListItem>
</div>
)
})
}
</List>
</div>
)
}
const CustomSearchBox = connectSearchBox(SearchBox)
const CustomAppHits = connectHits(AppHits)
const appView = isLoggedIn ? (
<Dropzone
@@ -1643,28 +1918,42 @@ const Apps = (props) => {
})}
</div>
) : (
<Paper square style={uploadViewPaperStyle}>
<Typography style={{ margin: 10 }}>
<span>
<a
rel="noopener noreferrer"
href={"https://shuffler.io/search"}
style={{ textDecoration: "none", color: "#f85a3e" }}
target="_blank"
>
Click here
</a>{" "}
to search ALL apps, not just your activated ones.
</span>
</Typography>
<div />
<Paper square style={{
minWidth: viewWidth,
maxWidth: viewWidth,
color: "white",
borderRadius: 5,
//display: "flex",
marginBottom: 10,
overflow: "hidden",
backgroundColor: theme.palette.platformColor,
border: null,
}}>
{appSearchLoading ? (
<CircularProgress
color="primary"
style={{ margin: "auto" }}
/>
) : null}
<div
style={{ textAlign: "center", width: leftBarSize, marginTop: 10 }}
onLoad={() => {
console.log("Should load in extra apps?")
}}
>
<Typography variant="body1" color="textSecondary">
Couldn't find the app you're looking for? Searching unactivated apps. Click one of the below apps to Activate it for your organization.
</Typography>
<InstantSearch searchClient={searchClient} indexName="appsearch" onClick={() => {
console.log("CLICKED")
}}>
<CustomSearchBox />
<Index indexName="appsearch">
<CustomAppHits />
</Index>
</InstantSearch>
</div>
</Paper>
)
) : isLoading ? (
+1 -1
View File
@@ -66,7 +66,7 @@ import { DataGrid, GridToolbar } from "@mui/x-data-grid";
//import JSONPretty from 'react-json-pretty';
//import JSONPrettyMon from 'react-json-pretty/dist/monikai'
import Dropzone from "../components/Dropzone";
import Dropzone from "../components/Dropzone.jsx";
import { useNavigate, Link, useParams } from "react-router-dom";
import { useAlert } from "react-alert";
+41 -24
View File
@@ -18,6 +18,7 @@ import {
} from '@mui/material';
import theme from '../theme';
import { useNavigate, Link } from "react-router-dom";
import Drift from "react-driftjs";
const Welcome = (props) => {
const { globalUrl, surfaceColor, newColor, mini, inputColor, userdata, isLoggedIn, isLoaded, serverside } = props;
@@ -25,7 +26,7 @@ const Welcome = (props) => {
const [inputUsecase, setInputUsecase] = useState({});
const [frameworkData, setFrameworkData] = useState(undefined);
const [discoveryWrapper, setDiscoveryWrapper] = useState(undefined);
const [activeStep, setActiveStep] = React.useState(0);
const [activeStep, setActiveStep] = React.useState(1);
const [apps, setApps] = React.useState([]);
const [defaultSearch, setDefaultSearch] = React.useState("")
const [selectionOpen, setSelectionOpen] = React.useState(false)
@@ -281,7 +282,8 @@ const Welcome = (props) => {
setActiveStep(foundTab-1)
} else {
navigate(`/welcome?tab=1`)
//navigate(`/welcome?tab=1`)
navigate(`/welcome?tab=2`)
}
}
}, [])
@@ -426,29 +428,31 @@ const Welcome = (props) => {
Who do you identify with the most?
</Typography>
<div style={{display: "flex", marginTop: 70, width: 700, margin: "auto",}}>
<Card style={paperObject} onClick={() => {
if (isCloud) {
ReactGA.event({
category: "welcome",
action: "click_welcome_continue",
label: "",
})
} else {
//setActiveStep(1)
}
<div style={{border: "1px solid #49A928",}}>
<Card style={paperObject} onClick={() => {
if (isCloud) {
ReactGA.event({
category: "welcome",
action: "click_welcome_continue",
label: "",
})
} else {
//setActiveStep(1)
}
setShowWelcome(true)
}}>
<CardActionArea style={actionObject}>
<Typography variant="h4" style={{color: "#49A928"}}>
New to Shuffle
</Typography>
<img src="/images/welcome_cog.png" style={imageStyle} />
<Typography variant="body1" style={{marginTop: 30, color: "rgba(255,255,255,0.8)"}}>
Follow our short introduction and learn some tips and tricks
</Typography>
</CardActionArea>
</Card>
setShowWelcome(true)
}}>
<CardActionArea style={actionObject}>
<Typography variant="h4" style={{color: "#49A928"}}>
New to Shuffle
</Typography>
<img src="/images/welcome_cog.png" style={imageStyle} />
<Typography variant="body1" style={{marginTop: 30, color: "rgba(255,255,255,0.8)"}}>
Follow our short introduction and learn some tips and tricks
</Typography>
</CardActionArea>
</Card>
</div>
<div style={{marginLeft: 25, marginRight: 25, }}>
<Typography style={{marginTop: 200, }}>
OR
@@ -476,6 +480,19 @@ const Welcome = (props) => {
</CardActionArea>
</Card>
</div>
{/*
<div style={{margin: "auto", border: "1px solid rgba(255,255,255,0.5)", borderRadius: theme.palette.borderRadius, marginTop: 50, width: 200, overflow: "wrap", padding: 25, cursor: "pointer", }} onClick={() => {
if (window.drift !== undefined) {
window.drift.api.startInteraction({ interactionId: 341911 })
} else {
console.log("Couldn't find drift in window.drift and not .drift-open-chat with querySelector: ", window.drift)
}
}}>
<Typography variant="body1" style={{margin: "auto", textAlign: "center"}}>
Want a free Proof of Value with our support team?
</Typography>
</div>
*/}
</div>
</Fade>
}
+3 -2
View File
@@ -89,7 +89,7 @@ import { DataGrid, GridToolbar } from "@mui/x-data-grid";
//import JSONPretty from 'react-json-pretty';
//import JSONPrettyMon from 'react-json-pretty/dist/monikai'
import Dropzone from "../components/Dropzone";
import Dropzone from "../components/Dropzone.jsx";
import { useNavigate, Link } from "react-router-dom";
import { useAlert } from "react-alert";
@@ -1262,8 +1262,9 @@ const Workflows = (props) => {
const exportAllWorkflows = (allWorkflows) => {
for (var i = 0; i < allWorkflows.length; i++) {
console.log(allWorkflows[i])
setTimeout(() => {
console.log(allWorkflows[i].name)
console.log(allWorkflows[i])
exportWorkflow(allWorkflows[i], false)
}, i * 200);
}