Fixed merge conflicts
This commit is contained in:
Regular → Executable
Regular → Executable
+12
-4
@@ -443,17 +443,17 @@ const Admin = (props) => {
|
||||
// Get drift username from userdata.username before @ in email
|
||||
const username = userdata.username.substring(0, userdata.username.indexOf("@"))
|
||||
|
||||
var body = `Hey,%0D%0AI saw you trying to use Shuffle, and thought we may be able to help. Right now, it looks like you have ${workflow_amount} workflows made, but I'm not sure if you're getting the most out of Shuffle.%0D%0A%0D%0AIf you're interested, I'd love to set up a quick call to see if we can help you get more out of Shuffle. %0D%0A%0D%0A
|
||||
var body = `Hey,%0D%0A%0D%0AI saw you trying to use Shuffle, and thought we may be able to help. Right now, it looks like you have ${workflow_amount} workflows made, but it still doesn't look like you are getting the most out of Shuffle. If you're interested, I'd love to set up a quick call to see if we can help you get more out of Shuffle. %0D%0A%0D%0A
|
||||
|
||||
Some of the things we can help with:%0D%0A
|
||||
${your_apps}
|
||||
- Properly authenticating and custom building apps%0D%0A
|
||||
- Configuring and authenticating your apps%0D%0A
|
||||
${usecases}
|
||||
- Creating special usecases%0D%0A%0D%0A
|
||||
- Creating special usecases and apps%0D%0A%0D%0A
|
||||
|
||||
Let me know if you're interested, or set up a call here: https://drift.me/${username}`
|
||||
|
||||
return `mailto:${admins}?subject=${subject}&body=${body}`
|
||||
return `mailto:${admins}?bcc=frikky@shuffler.io&subject=${subject}&body=${body}`
|
||||
}
|
||||
|
||||
const deleteAuthentication = (data) => {
|
||||
@@ -3532,8 +3532,12 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
|
||||
<div style={{ marginTop: 20, marginBottom: 20 }}>
|
||||
<h2 style={{ display: "inline" }}>App Authentication</h2>
|
||||
<span style={{ marginLeft: 25 }}>
|
||||
<<<<<<< HEAD
|
||||
Control the authentication options for individual apps. PS: Actions
|
||||
performed here can be destructive!
|
||||
=======
|
||||
Control the authentication options for individual apps.
|
||||
>>>>>>> master
|
||||
</span>
|
||||
|
||||
<a
|
||||
@@ -3542,7 +3546,11 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
|
||||
href="/docs/organizations#app_authentication"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
>
|
||||
<<<<<<< HEAD
|
||||
Learn more about authentication
|
||||
=======
|
||||
Learn more about App Authentication
|
||||
>>>>>>> master
|
||||
</a>
|
||||
</div>
|
||||
<Divider
|
||||
|
||||
Regular → Executable
Regular → Executable
+42
-21
@@ -4638,7 +4638,8 @@ const AngularWorkflow = (defaultprops) => {
|
||||
};
|
||||
|
||||
const addSuggestionButtons = (nodedata, event) => {
|
||||
//console.log("In suggestion buttons: ", nodedata, ". This is not enabled yet. Backend needs further work.")
|
||||
console.log("In suggestion buttons: ", nodedata, ". This is not enabled yet. Backend needs further work.")
|
||||
return
|
||||
// Skipping add for now. Should Re-enable
|
||||
|
||||
// Add a button for autocompletion based on input
|
||||
@@ -4677,8 +4678,6 @@ const AngularWorkflow = (defaultprops) => {
|
||||
|
||||
cy.add(decoratorNode);
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
//setWorkflowRecommendations(responseJson.actions)
|
||||
if (workflowRecommendations.length === 0) {
|
||||
@@ -14561,9 +14560,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
? "red"
|
||||
: yellow;
|
||||
|
||||
const validate = !codeModalOpen
|
||||
? ""
|
||||
: validateJson(selectedResult.result.trim());
|
||||
const validate = ! codeModalOpen? "" : validateJson(selectedResult.result.trim());
|
||||
|
||||
if (validate.valid && typeof validate.result === "string") {
|
||||
validate.result = JSON.parse(validate.result);
|
||||
@@ -14573,12 +14570,17 @@ const AngularWorkflow = (defaultprops) => {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const showVariable = data.value.length < 60
|
||||
|
||||
// Check if it's valid JSON
|
||||
const checked = validateJson(data.value.trim())
|
||||
|
||||
return (
|
||||
<div style={{ maxWidth: 600, overflowX: "hidden", }}>
|
||||
{data.value.length > 60 ?
|
||||
{data.value.length > 60 || checked.valid ?
|
||||
<IconButton
|
||||
style={{
|
||||
marginBottom: 0, marginTop: 5, cursor: "pointer",
|
||||
marginBottom: 0,
|
||||
marginTop: 5,
|
||||
cursor: "pointer",
|
||||
padding: 3,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
@@ -14593,7 +14595,16 @@ const AngularWorkflow = (defaultprops) => {
|
||||
variant="body1"
|
||||
style={{}}
|
||||
>
|
||||
<b>{data.name}</b> {showVariable ? data.value : null}
|
||||
<b>{data.name}</b>
|
||||
{checked.valid ?
|
||||
<Chip
|
||||
style={{marginLeft: 10, padding: 0, cursor: "pointer",}}
|
||||
label={"JSON"}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
/>
|
||||
: null}
|
||||
{showVariable ? data.value : null}
|
||||
</Typography>
|
||||
</IconButton>
|
||||
:
|
||||
@@ -14605,15 +14616,25 @@ const AngularWorkflow = (defaultprops) => {
|
||||
</Typography>
|
||||
}
|
||||
{open ?
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{
|
||||
whiteSpace: 'pre-line',
|
||||
}}
|
||||
color="textSecondary"
|
||||
>
|
||||
{data.value}
|
||||
</Typography>
|
||||
checked.valid ?
|
||||
<ReactJson
|
||||
src={checked.result}
|
||||
theme={theme.palette.jsonTheme}
|
||||
style={theme.palette.reactJsonStyle}
|
||||
collapsed={data.value.length < 10000 ? false : true}
|
||||
displayDataTypes={false}
|
||||
name={"Parsed data for variable " + data.name}
|
||||
/>
|
||||
:
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{
|
||||
whiteSpace: 'pre-line',
|
||||
}}
|
||||
color="textSecondary"
|
||||
>
|
||||
{data.value}
|
||||
</Typography>
|
||||
: null}
|
||||
</div>
|
||||
)
|
||||
@@ -15071,10 +15092,10 @@ const AngularWorkflow = (defaultprops) => {
|
||||
>
|
||||
<FormControl>
|
||||
<DialogTitle id="draggable-dialog-title" style={{ cursor: "move", }}>
|
||||
<span style={{ color: "white" }}>Execution Variable</span>
|
||||
<span style={{ color: "white" }}>Runtime Variable</span>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
Execution Variables are TEMPORARY variables that you can only be set
|
||||
Runtime Variables are TEMPORARY variables that you can only be set
|
||||
and used during execution. Learn more{" "}
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
@@ -15095,7 +15116,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
},
|
||||
}}
|
||||
margin="dense"
|
||||
label="Name"
|
||||
label="Name"
|
||||
fullWidth
|
||||
defaultValue={newVariableName}
|
||||
/>
|
||||
|
||||
Regular → Executable
Regular → Executable
Executable
+345
@@ -0,0 +1,345 @@
|
||||
import React, { useState } from 'react';
|
||||
import { BrowserView, MobileView } from "react-device-detect";
|
||||
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
|
||||
import { useTheme } from '@material-ui/core/styles';
|
||||
|
||||
const bodyDivStyle = {
|
||||
margin: "auto",
|
||||
textAlign: "center",
|
||||
width: "900px",
|
||||
}
|
||||
|
||||
|
||||
// Should be different if logged in :|
|
||||
const Contact = (props) => {
|
||||
const { globalUrl, isLoaded } = props;
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const boxStyle = {
|
||||
flex: "1",
|
||||
marginLeft: "10px",
|
||||
marginRight: "10px",
|
||||
paddingLeft: "30px",
|
||||
paddingRight: "30px",
|
||||
paddingBottom: "30px",
|
||||
paddingTop: "30px",
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
display: "flex",
|
||||
flexDirection: "column"
|
||||
}
|
||||
|
||||
const bodyTextStyle = {
|
||||
color: "#ffffff",
|
||||
}
|
||||
|
||||
const [firstname, setFirstname] = useState("");
|
||||
const [lastname, setLastname] = useState("");
|
||||
const [title, setTitle] = useState("");
|
||||
const [companyname, setCompanyname] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [phone, setPhone] = useState("");
|
||||
const [message, setMessage] = useState("");
|
||||
|
||||
const [formMessage, setFormMessage] = useState("");
|
||||
|
||||
const submitContact = () => {
|
||||
const data = {
|
||||
"firstname": firstname,
|
||||
"lastname": lastname,
|
||||
"title": title,
|
||||
"companyname": companyname,
|
||||
"email": email,
|
||||
"phone": phone,
|
||||
"message": message,
|
||||
}
|
||||
console.log(data)
|
||||
|
||||
fetch(globalUrl + "/api/v1/contact", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
if (response.success === true) {
|
||||
setFormMessage(response.message)
|
||||
} else {
|
||||
setFormMessage("Something went wrong. Please contact frikky@shuffler.io.")
|
||||
}
|
||||
console.log(response)
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
}
|
||||
|
||||
// Random names for type & autoComplete. Didn't research :^)
|
||||
const landingpageDataBrowser =
|
||||
<div>
|
||||
<div style={bodyTextStyle}>
|
||||
<h3 style={{ color: "#f85a3e" }}>Contact us</h3>
|
||||
<h2>Lets talk!</h2>
|
||||
</div>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Paper style={boxStyle}>
|
||||
<h2>Contact Details</h2>
|
||||
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
|
||||
<TextField
|
||||
required
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
fullWidth={true}
|
||||
placeholder="First Name"
|
||||
type="firstname"
|
||||
id="standard-required"
|
||||
autoComplete="firstname"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setFirstname(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
fullWidth={true}
|
||||
placeholder="Last Name"
|
||||
type="lastname"
|
||||
id="standard"
|
||||
autoComplete="lastname"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setLastname(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
|
||||
<TextField
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
fullWidth={true}
|
||||
placeholder="Job Title"
|
||||
type="jobtitle"
|
||||
id="standard-required"
|
||||
autoComplete="jobtitle"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setTitle(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
fullWidth={true}
|
||||
type="companyname"
|
||||
placeholder="Company Name"
|
||||
id="standard-required"
|
||||
autoComplete="companyname"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setCompanyname(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
|
||||
<TextField
|
||||
required
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
fullWidth={true}
|
||||
placeholder="Email"
|
||||
type="email"
|
||||
id="standard-required"
|
||||
autoComplete="email"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
fullWidth={true}
|
||||
type="phone"
|
||||
placeholder="Phone number"
|
||||
id="standard-required"
|
||||
autoComplete="phone"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setPhone(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<h2>Message</h2>
|
||||
</div>
|
||||
<div style={{ flex: 4 }}>
|
||||
<TextField
|
||||
multiline
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
|
||||
rows="6"
|
||||
fullWidth={true}
|
||||
placeholder="What can we help you with?"
|
||||
id="filled-multiline-static"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setMessage(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
disabled={email.length <= 0 || message.length <= 0}
|
||||
style={{ width: "100%", height: "60px", marginTop: "10px" }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={submitContact}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
<h3>{formMessage}</h3>
|
||||
</Paper>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
const landingpageDataMobile =
|
||||
<div style={{ paddingBottom: "50px" }}>
|
||||
<div style={{ color: "white", textAlign: "center" }}>
|
||||
<h3 style={{ color: "#f85a3e" }}>Contact us</h3>
|
||||
<h2>Lets talk!</h2>
|
||||
</div>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Paper style={boxStyle}>
|
||||
<h2>Contact Details</h2>
|
||||
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
|
||||
<TextField
|
||||
required
|
||||
style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
fullWidth={true}
|
||||
placeholder="Name"
|
||||
type="firstname"
|
||||
id="standard-required"
|
||||
autoComplete="firstname"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setFirstname(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
|
||||
<TextField
|
||||
required
|
||||
style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
fullWidth={true}
|
||||
placeholder="Email"
|
||||
type="email"
|
||||
id="standard-required"
|
||||
autoComplete="email"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<h2>Message</h2>
|
||||
</div>
|
||||
<div style={{ flex: 4 }}>
|
||||
<TextField
|
||||
multiline
|
||||
style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
rows="6"
|
||||
fullWidth={true}
|
||||
placeholder="What can we help you with?"
|
||||
id="filled-multiline-static"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={e => setMessage(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
disabled={email.length <= 0 || message.length <= 0}
|
||||
style={{ width: "100%", height: "60px", marginTop: "10px" }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={submitContact}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
<h3>{formMessage}</h3>
|
||||
</Paper>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
const loadedCheck = isLoaded ?
|
||||
<div>
|
||||
<BrowserView>
|
||||
<div style={bodyDivStyle}>{landingpageDataBrowser}</div>
|
||||
</BrowserView>
|
||||
<MobileView>
|
||||
{landingpageDataMobile}
|
||||
</MobileView>
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
|
||||
return (
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Contact;
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+26
-19
@@ -6,10 +6,16 @@ import theme from '../theme.jsx';
|
||||
const SetAuthentication = (props) => {
|
||||
const { globalUrl } = props;
|
||||
|
||||
var headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
}
|
||||
|
||||
const [firstRequest, setFirstRequest] = useState(true);
|
||||
const [finished, setFinished] = useState(false);
|
||||
const [response, setResponse] = useState("");
|
||||
const [failed, setFailed] = useState(false);
|
||||
const [requestHeaders, setRequestHeaders] = useState(headers);
|
||||
|
||||
if (firstRequest) {
|
||||
setFirstRequest(false);
|
||||
@@ -20,6 +26,8 @@ const SetAuthentication = (props) => {
|
||||
const params = Object.fromEntries(urlSearchParams.entries());
|
||||
console.log("PARAMS: ", params)
|
||||
|
||||
|
||||
|
||||
//const authenticationStore = [];
|
||||
var appAuthData = {
|
||||
label: "",
|
||||
@@ -40,7 +48,6 @@ const SetAuthentication = (props) => {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (params.session_state !== undefined && params.session_state !== null) {
|
||||
appAuthData.fields.push({
|
||||
key: "session_state",
|
||||
@@ -83,6 +90,14 @@ const SetAuthentication = (props) => {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (query[0] === "org_id") {
|
||||
headers["Org-Id"] = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "authorization") {
|
||||
headers["Authorization"] = "Bearer " + query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "workflow_id") {
|
||||
appAuthData.reference_workflow = query[1];
|
||||
}
|
||||
@@ -136,6 +151,8 @@ const SetAuthentication = (props) => {
|
||||
appAuthData.fields.push({ key: "refresh_url", value: query[1] });
|
||||
}
|
||||
}
|
||||
|
||||
setRequestHeaders(headers)
|
||||
}
|
||||
|
||||
if (foundScope !== undefined && foundScope !== null && foundScope.length > 0) {
|
||||
@@ -153,15 +170,13 @@ const SetAuthentication = (props) => {
|
||||
setFailed(true)
|
||||
setResponse(`${foundTab}`)
|
||||
} else {
|
||||
|
||||
if (externalData.handleExternal) {
|
||||
console.log("RUN EXTERNAL!!: ", externalData)
|
||||
|
||||
fetch(globalUrl + "/api/v1/triggers/github/register", {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
headers: requestHeaders,
|
||||
credentials: "include",
|
||||
body: JSON.stringify(externalData),
|
||||
})
|
||||
@@ -191,7 +206,6 @@ const SetAuthentication = (props) => {
|
||||
.then((responseJson) => {
|
||||
//setUserSettings(responseJson)
|
||||
console.log("Resp: ", responseJson);
|
||||
|
||||
if (responseJson.reason !== undefined) {
|
||||
setResponse(responseJson.reason);
|
||||
setFinished(true);
|
||||
@@ -227,23 +241,16 @@ const SetAuthentication = (props) => {
|
||||
|
||||
fetch(globalUrl + "/api/v1/apps/authentication", {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
headers: requestHeaders,
|
||||
credentials: "include",
|
||||
body: JSON.stringify(appAuthData),
|
||||
})
|
||||
.then((response) => {
|
||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||
const tmpView = new URLSearchParams(cursearch).get("state");
|
||||
if (
|
||||
tmpView !== undefined &&
|
||||
tmpView !== null &&
|
||||
tmpView.length > 0
|
||||
) {
|
||||
console.log("State to find app name from: ", tmpView)
|
||||
}
|
||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||
const tmpView = new URLSearchParams(cursearch).get("state");
|
||||
if (tmpView !== undefined && tmpView !== null && tmpView.length > 0) {
|
||||
console.log("State to find app name from: ", tmpView)
|
||||
}
|
||||
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for oauth2 authentication");
|
||||
|
||||
Regular → Executable
Regular → Executable
@@ -0,0 +1,172 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import ReactGA from "react-ga4";
|
||||
import {
|
||||
Typography,
|
||||
CircularProgress,
|
||||
Button,
|
||||
} from "@material-ui/core";
|
||||
import theme from '../theme.jsx';
|
||||
import { useAlert } from "react-alert";
|
||||
|
||||
import AuthenticationOauth2 from "../components/Oauth2Auth.jsx";
|
||||
import AuthenticationWindow from "../components/AuthenticationWindow.jsx";
|
||||
import { base64_decode, appCategories } from "../views/AppCreator.jsx";
|
||||
|
||||
const SetAuthentication = (props) => {
|
||||
const { globalUrl, serverside } = props;
|
||||
|
||||
const [app, setApp] = useState({});
|
||||
const [isAppLoaded, setIsAppLoaded] = useState(false);
|
||||
const [loadFail, setLoadFail] = useState("");
|
||||
const [appAuthentication, setAppAuthentication] = React.useState([]);
|
||||
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||
const alert = useAlert();
|
||||
|
||||
const parseIncomingOpenapiData = (data) => {
|
||||
if (data.app === undefined || data.app === null) {
|
||||
return
|
||||
}
|
||||
|
||||
// Should basically always be true if openapi exists too
|
||||
var parsedBaseapp = ""
|
||||
try {
|
||||
parsedBaseapp = base64_decode(data.app)
|
||||
} catch (e) {
|
||||
console.log("Failed JSON parsing: ", e)
|
||||
parsedBaseapp = data
|
||||
}
|
||||
|
||||
var parsedapp = JSON.parse(parsedBaseapp)
|
||||
parsedapp.name = parsedapp.name.replaceAll("_", " ");
|
||||
setApp(parsedapp);
|
||||
|
||||
document.title = parsedapp.name + " App Auth";
|
||||
|
||||
}
|
||||
|
||||
console.log("App: ", app)
|
||||
|
||||
const getApp = (appid) => {
|
||||
if (serverside === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`${globalUrl}/api/v1/apps/${appid}/config`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
category: "appauth",
|
||||
action: `app_not_found`,
|
||||
label: appid,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
category: "appauth",
|
||||
action: `app_found`,
|
||||
label: appid,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success === false || responseJson.success === undefined) {
|
||||
alert.error("Failed to get the app. Does it exist?")
|
||||
setIsAppLoaded(true)
|
||||
return;
|
||||
}
|
||||
|
||||
parseIncomingOpenapiData(responseJson);
|
||||
})
|
||||
.catch((error) => {
|
||||
alert.error("Error in app fetch: " + error.toString());
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Find the ID for the app from the "app_id" query
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const appid = urlParams.get("app_id");
|
||||
if (appid === null) {
|
||||
setLoadFail(
|
||||
<span>
|
||||
<Typography variant="h4">
|
||||
Failed to load the app. Please contact your provider or support@shuffler.io if this persists
|
||||
</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => window.location.reload()}
|
||||
>
|
||||
Reload Window
|
||||
</Button>
|
||||
</span>
|
||||
)
|
||||
} else {
|
||||
getApp(appid);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Handle:
|
||||
// 1. Check for org_id, authentication, and app keys in queries
|
||||
// 2. Load the app auth info from the orgs' apps
|
||||
// 3. Help them set info for the app
|
||||
// Make sure to test both private and public apps
|
||||
|
||||
const appname = app.name !== undefined ? app.name : "";
|
||||
|
||||
return (
|
||||
<div style={{width: 1000, margin: "auto", marginTop: 50, }}>
|
||||
{loadFail !== "" ?
|
||||
loadFail
|
||||
:
|
||||
<div>
|
||||
<Typography variant="h4" style={{marginBottom: 20,}}>
|
||||
Configure {appname} Authentication
|
||||
</Typography>
|
||||
{app.authentication === undefined || app.authentication === null || app.authentication.length === 0 ?
|
||||
null
|
||||
:
|
||||
app.authentication.type === "oauth2" ?
|
||||
<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={undefined}
|
||||
/>
|
||||
:
|
||||
<AuthenticationWindow
|
||||
globalUrl={globalUrl}
|
||||
selectedApp={app}
|
||||
authFieldsOnly={true}
|
||||
getAppAuthentication={undefined}
|
||||
appAuthentication={appAuthentication}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
export default SetAuthentication;
|
||||
Regular → Executable
Regular → Executable
+15
-1
@@ -462,7 +462,21 @@ export const validateJson = (showResult) => {
|
||||
try {
|
||||
var newstr = showResult.replaceAll("'", '"')
|
||||
|
||||
//console.log("Try replacements and trimming with new value: ", newstr)
|
||||
// Basic workarounds for issues with Python Dicts -> JSON
|
||||
if (newstr.includes(": None")) {
|
||||
newstr = newstr.replaceAll(": None", ': null')
|
||||
}
|
||||
|
||||
if (newstr.includes("[\"{") && newstr.includes("}\"]")) {
|
||||
newstr = newstr.replaceAll("[\"{", '[{')
|
||||
newstr = newstr.replaceAll("}\"]", '}]')
|
||||
}
|
||||
|
||||
if (newstr.includes("{\"[") && newstr.includes("]\"}")) {
|
||||
newstr = newstr.replaceAll("{\"[", '[{')
|
||||
newstr = newstr.replaceAll("]\"}", '}]')
|
||||
}
|
||||
|
||||
result = JSON.parse(newstr)
|
||||
jsonvalid = true
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user