Revert "Launch"
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
# Certificate:
|
||||
|
||||
Creating a localhost certificate:
|
||||
|
||||
```
|
||||
|
||||
@@ -93,7 +93,6 @@
|
||||
"not op_mini all"
|
||||
],
|
||||
"devDependencies": {
|
||||
"prettier": "2.4.1",
|
||||
"promise-window": "^1.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||
/>
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<meta charset="utf-8">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<title>Shuffle</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
+125
-442
@@ -1,9 +1,9 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import { Route } from "react-router";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { CookiesProvider } from "react-cookie";
|
||||
import { removeCookies, useCookies } from "react-cookie";
|
||||
import { Route } from 'react-router';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import { CookiesProvider } from 'react-cookie';
|
||||
import { removeCookies, useCookies } from 'react-cookie';
|
||||
|
||||
import EditSchedule from "./views/EditSchedule";
|
||||
import Schedules from "./views/Schedules";
|
||||
@@ -12,10 +12,10 @@ import Workflows from "./views/Workflows";
|
||||
import EditWebhook from "./views/EditWebhook";
|
||||
import AngularWorkflow from "./views/AngularWorkflow";
|
||||
|
||||
import Header from "./components/Header";
|
||||
import theme from "./theme";
|
||||
import Apps from "./views/Apps";
|
||||
import AppCreator from "./views/AppCreator";
|
||||
import Header from './components/Header';
|
||||
import theme from './theme'
|
||||
import Apps from './views/Apps';
|
||||
import AppCreator from './views/AppCreator';
|
||||
|
||||
import Dashboard from "./views/Dashboard";
|
||||
import AdminSetup from "./views/AdminSetup";
|
||||
@@ -31,228 +31,186 @@ import SettingsPage from "./views/SettingsPage";
|
||||
|
||||
import MyView from "./views/MyView";
|
||||
|
||||
import { createMuiTheme, MuiThemeProvider } from "@material-ui/core/styles";
|
||||
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles';
|
||||
|
||||
import ScrollToTop from "./components/ScrollToTop";
|
||||
import AlertTemplate from "./components/AlertTemplate";
|
||||
import { positions, Provider } from "react-alert";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import {isMobile} from "react-device-detect";
|
||||
|
||||
import detectEthereumProvider from "@metamask/detect-provider";
|
||||
import detectEthereumProvider from '@metamask/detect-provider';
|
||||
|
||||
// Production - backend proxy forwarding in nginx
|
||||
var globalUrl = window.location.origin;
|
||||
var globalUrl = window.location.origin
|
||||
|
||||
// CORS used for testing purposes. Should only happen with specific port and http
|
||||
if (window.location.port === "3000") {
|
||||
globalUrl = "http://localhost:5001";
|
||||
if ( window.location.port === "3000") {
|
||||
globalUrl = "http://localhost:5001"
|
||||
//globalUrl = "http://localhost:5002"
|
||||
}
|
||||
|
||||
const App = (message, props) => {
|
||||
const [userdata, setUserData] = useState({});
|
||||
const [notifications, setNotifications] = useState([]);
|
||||
const [cookies, setCookie, removeCookie] = useCookies([]);
|
||||
const [notifications, setNotifications] = useState([])
|
||||
const [cookies, setCookie, removeCookie] = useCookies([])
|
||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
||||
const [dataset, setDataset] = useState(false);
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
const [curpath, setCurpath] = useState(
|
||||
typeof window === "undefined" || window.location === undefined
|
||||
? ""
|
||||
: window.location.pathname
|
||||
);
|
||||
const [curpath, setCurpath] = useState(typeof window === 'undefined' || window.location === undefined ? "" : window.location.pathname)
|
||||
|
||||
useEffect(() => {
|
||||
if (dataset === false) {
|
||||
getUserNotifications();
|
||||
checkLogin();
|
||||
setDataset(true);
|
||||
getUserNotifications()
|
||||
checkLogin()
|
||||
setDataset(true)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if (
|
||||
isLoaded &&
|
||||
!isLoggedIn &&
|
||||
!window.location.pathname.startsWith("/login") &&
|
||||
!window.location.pathname.startsWith("/docs") &&
|
||||
!window.location.pathname.startsWith("/adminsetup")
|
||||
) {
|
||||
window.location = "/login";
|
||||
if (isLoaded && !isLoggedIn && (!window.location.pathname.startsWith("/login") && (!window.location.pathname.startsWith("/docs") && (!window.location.pathname.startsWith("/adminsetup"))))) {
|
||||
window.location = "/login"
|
||||
}
|
||||
|
||||
const getUserNotifications = () => {
|
||||
fetch(`${globalUrl}/api/v1/notifications`, {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
if (
|
||||
responseJson.success === true &&
|
||||
responseJson.notifications !== null &&
|
||||
responseJson.notifications !== undefined &&
|
||||
responseJson.notifications.length > 0
|
||||
) {
|
||||
.then(response => response.json())
|
||||
.then(responseJson => {
|
||||
if (responseJson.success === true && responseJson.notifications !== null && responseJson.notifications !== undefined && responseJson.notifications.length > 0) {
|
||||
//console.log("RESP: ", responseJson)
|
||||
setNotifications(responseJson.notifications);
|
||||
setNotifications(responseJson.notifications)
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("Failed getting notifications for user: ", error);
|
||||
.catch(error => {
|
||||
console.log("Failed getting notifications for user: ", error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const checkLogin = () => {
|
||||
var baseurl = globalUrl;
|
||||
var baseurl = globalUrl
|
||||
fetch(baseurl + "/api/v1/users/getinfo", {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
var userInfo = {};
|
||||
.then(response => response.json())
|
||||
.then(responseJson => {
|
||||
var userInfo = {}
|
||||
if (responseJson.success === true) {
|
||||
console.log(responseJson);
|
||||
console.log(responseJson)
|
||||
|
||||
userInfo = responseJson;
|
||||
setIsLoggedIn(true);
|
||||
userInfo = responseJson
|
||||
setIsLoggedIn(true)
|
||||
//console.log("Cookies: ", cookies)
|
||||
// Updating cookie every request
|
||||
for (var key in responseJson["cookies"]) {
|
||||
setCookie(
|
||||
responseJson["cookies"][key].key,
|
||||
responseJson["cookies"][key].value,
|
||||
{ path: "/" }
|
||||
);
|
||||
setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, { path: "/" })
|
||||
}
|
||||
}
|
||||
|
||||
// Handling Ethereum update
|
||||
detectEthereumProvider().then((provider) => {
|
||||
if (
|
||||
provider &&
|
||||
userInfo.eth_info !== undefined &&
|
||||
userInfo.eth_info !== null
|
||||
) {
|
||||
if (
|
||||
userInfo.eth_info.account !== undefined &&
|
||||
userInfo.eth_info.account !== null &&
|
||||
userInfo.eth_info.account.length === 0
|
||||
) {
|
||||
userInfo.eth_info = {};
|
||||
var method = "eth_requestAccounts";
|
||||
var params = [];
|
||||
provider
|
||||
.request({
|
||||
detectEthereumProvider()
|
||||
.then((provider) => {
|
||||
if (provider && userInfo.eth_info !== undefined && userInfo.eth_info !== null) {
|
||||
if (userInfo.eth_info.account !== undefined && userInfo.eth_info.account !== null && userInfo.eth_info.account.length === 0) {
|
||||
userInfo.eth_info = {}
|
||||
var method = "eth_requestAccounts"
|
||||
var params = []
|
||||
provider.request({
|
||||
method: method,
|
||||
params,
|
||||
})
|
||||
.then((result) => {
|
||||
if (
|
||||
result !== undefined &&
|
||||
result !== null &&
|
||||
result.length > 0
|
||||
) {
|
||||
userInfo.eth_info.account = result[0];
|
||||
if (result !== undefined && result !== null && result.length > 0) {
|
||||
userInfo.eth_info.account = result[0]
|
||||
|
||||
// Getting and setting balance for the current user
|
||||
method = "eth_getBalance";
|
||||
params = [userInfo.eth_info.account, "latest"];
|
||||
provider
|
||||
.request({
|
||||
method = "eth_getBalance"
|
||||
params = [
|
||||
userInfo.eth_info.account,
|
||||
"latest"
|
||||
]
|
||||
provider.request({
|
||||
method: method,
|
||||
params,
|
||||
})
|
||||
.then((result) => {
|
||||
if (
|
||||
result !== undefined &&
|
||||
result !== null &&
|
||||
result.length > 0
|
||||
) {
|
||||
userInfo.parsed_balance =
|
||||
result / 1000000000000000000;
|
||||
if (result !== undefined && result !== null && result.length > 0) {
|
||||
userInfo.parsed_balance = result/1000000000000000000
|
||||
} else {
|
||||
alert.error("Couldn't find balance: ", result);
|
||||
alert.error("Couldn't find balance: ", result)
|
||||
}
|
||||
// The result varies by RPC method.
|
||||
// For example, this method will return a transaction hash hexadecimal string on success.
|
||||
})
|
||||
.catch((error) => {
|
||||
// If the request fails, the Promise will reject with an error.
|
||||
alert.error(
|
||||
"Failed getting info from ethereum API: " + error
|
||||
);
|
||||
});
|
||||
alert.error("Failed getting info from ethereum API: "+error)
|
||||
})
|
||||
} else {
|
||||
alert.error("Couldn't find any user: ", result);
|
||||
alert.error("Couldn't find any user: ", result)
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
// If the request fails, the Promise will reject with an error.
|
||||
alert.error(
|
||||
"Failed getting info from ethereum API: " + error
|
||||
);
|
||||
});
|
||||
alert.error("Failed getting info from ethereum API: "+error)
|
||||
})
|
||||
}
|
||||
|
||||
// Register hooks here
|
||||
provider.on("message", (event) => {
|
||||
alert.info("Message from MetaMask: ", event);
|
||||
});
|
||||
provider.on('message', (event) => {
|
||||
alert.info("Message from MetaMask: ", event)
|
||||
})
|
||||
|
||||
provider.on("chainChanged", (chainId) => {
|
||||
console.log("Changed chain to: ", chainId);
|
||||
provider.on('chainChanged', (chainId) => {
|
||||
console.log("Changed chain to: ", chainId)
|
||||
|
||||
method = "eth_getBalance";
|
||||
params = [userInfo.eth_info.account, "latest"];
|
||||
provider
|
||||
.request({
|
||||
method = "eth_getBalance"
|
||||
params = [
|
||||
userInfo.eth_info.account,
|
||||
"latest"
|
||||
]
|
||||
provider.request({
|
||||
method: method,
|
||||
params,
|
||||
})
|
||||
.then((result) => {
|
||||
console.log("Got result: ", result);
|
||||
console.log("Got result: ", result)
|
||||
if (result !== undefined && result !== null) {
|
||||
userInfo.eth_info.balance = result;
|
||||
userInfo.eth_info.parsed_balance =
|
||||
result / 1000000000000000000;
|
||||
console.log("INFO: ", userInfo);
|
||||
setUserData(userInfo);
|
||||
userInfo.eth_info.balance = result
|
||||
userInfo.eth_info.parsed_balance = result/1000000000000000000
|
||||
console.log("INFO: ", userInfo)
|
||||
setUserData(userInfo)
|
||||
} else {
|
||||
alert.error("Couldn't find balance: ", result);
|
||||
alert.error("Couldn't find balance: ", result)
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
// If the request fails, the Promise will reject with an error.
|
||||
alert.error(
|
||||
"Failed getting info from ethereum API: " + error
|
||||
);
|
||||
});
|
||||
});
|
||||
alert.error("Failed getting info from ethereum API: "+error)
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if (
|
||||
userInfo.eth_info !== undefined &&
|
||||
userInfo.eth_info.balance !== undefined
|
||||
) {
|
||||
if (userInfo.eth_info !== undefined && userInfo.eth_info.balance !== undefined) {
|
||||
//console.log(userInfo.eth_info.balance)
|
||||
userInfo.eth_info.parsed_balance =
|
||||
userInfo.eth_info.balance / 1000000000000000000;
|
||||
userInfo.eth_info.parsed_balance = userInfo.eth_info.balance/1000000000000000000
|
||||
}
|
||||
|
||||
//console.log("USER: ", userInfo)
|
||||
setUserData(userInfo);
|
||||
setIsLoaded(true);
|
||||
setUserData(userInfo)
|
||||
setIsLoaded(true)
|
||||
|
||||
})
|
||||
.catch((error) => {
|
||||
setIsLoaded(true);
|
||||
.catch(error => {
|
||||
setIsLoaded(true)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Dumb for content load (per now), but good for making the site not suddenly reload parts (ajax thingies)
|
||||
|
||||
@@ -261,314 +219,39 @@ const App = (message, props) => {
|
||||
position: positions.BOTTOM_LEFT,
|
||||
};
|
||||
|
||||
const includedData =
|
||||
window.location.pathname === "/home" ||
|
||||
window.location.pathname === "/features" ? (
|
||||
const includedData = window.location.pathname === "/home" || window.location.pathname === "/features" ?
|
||||
<div>
|
||||
<Route
|
||||
exact
|
||||
path="/home"
|
||||
render={(props) => <LandingPageNew isLoaded={isLoaded} {...props} />}
|
||||
/>
|
||||
<Route exact path="/home" render={props => <LandingPageNew isLoaded={isLoaded} {...props} />} />
|
||||
</div> :
|
||||
<div style={{ backgroundColor: "#1F2023", color: "rgba(255, 255, 255, 0.65)", minHeight: "100vh" }}>
|
||||
<ScrollToTop getUserNotifications={getUserNotifications} setCurpath={setCurpath} />
|
||||
<Header notifications={notifications} setNotifications={setNotifications} checkLogin={checkLogin} cookies={cookies} removeCookie={removeCookie} isLoaded={isLoaded} globalUrl={globalUrl} setIsLoggedIn={setIsLoggedIn} isLoggedIn={isLoggedIn} userdata={userdata} {...props} />
|
||||
<div style={{height: 60}}/>
|
||||
<Route exact path="/login" render={props => <LoginPage isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} checkLogin={checkLogin} {...props} />} />
|
||||
<Route exact path="/admin" render={props => <Admin userdata={userdata} isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
|
||||
<Route exact path="/admin/:key" render={props => <Admin isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
|
||||
{userdata.id !== undefined ?
|
||||
<Route exact path="/settings" render={props => <SettingsPage isLoaded={isLoaded} setUserData={setUserData} userdata={userdata} globalUrl={globalUrl} {...props} />} />
|
||||
: null}
|
||||
<Route exact path="/AdminSetup" render={props => <AdminSetup isLoaded={isLoaded} userdata={userdata} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/webhooks" render={props => <Webhooks isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/webhooks/:key" render={props => <EditWebhook isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/schedules" render={props => <Schedules globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/dashboard" render={props => <Dashboard isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/apps/new" render={props => <AppCreator isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/apps" render={props => <Apps isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} userdata={userdata} {...props} />} />
|
||||
<Route exact path="/apps/edit/:appid" render={props => <AppCreator isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/schedules/:key" render={props => <EditSchedule globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/workflows" render={props => <Workflows cookies={cookies} removeCookie={removeCookie} isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} cookies={cookies} userdata={userdata} {...props} />} />
|
||||
<Route exact path="/workflows/:key" render={props => <AngularWorkflow userdata={userdata} globalUrl={globalUrl} isLoaded={isLoaded} isLoggedIn={isLoggedIn} {...props} />} />
|
||||
<Route exact path="/docs/:key" render={props => <Docs isMobile={isMobile} isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/docs" render={props => { window.location.pathname = "/docs/about" }} />
|
||||
<Route exact path="/introduction" render={props => <Introduction isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/introduction/:key" render={props => <Introduction isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
|
||||
<Route exact path="/set_authentication" render={props => <SetAuthentication userdata={userdata} isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
|
||||
<Route exact path="/login_sso" render={props => <SetAuthenticationSSO userdata={userdata} isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
|
||||
<Route exact path="/" render={props => <LoginPage isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "#1F2023",
|
||||
color: "rgba(255, 255, 255, 0.65)",
|
||||
minHeight: "100vh",
|
||||
}}
|
||||
>
|
||||
<ScrollToTop
|
||||
getUserNotifications={getUserNotifications}
|
||||
setCurpath={setCurpath}
|
||||
/>
|
||||
<Header
|
||||
notifications={notifications}
|
||||
setNotifications={setNotifications}
|
||||
checkLogin={checkLogin}
|
||||
cookies={cookies}
|
||||
removeCookie={removeCookie}
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
setIsLoggedIn={setIsLoggedIn}
|
||||
isLoggedIn={isLoggedIn}
|
||||
userdata={userdata}
|
||||
{...props}
|
||||
/>
|
||||
<div style={{ height: 60 }} />
|
||||
<Route
|
||||
exact
|
||||
path="/login"
|
||||
render={(props) => (
|
||||
<LoginPage
|
||||
isLoggedIn={isLoggedIn}
|
||||
setIsLoggedIn={setIsLoggedIn}
|
||||
register={true}
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
setCookie={setCookie}
|
||||
cookies={cookies}
|
||||
checkLogin={checkLogin}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/admin"
|
||||
render={(props) => (
|
||||
<Admin
|
||||
userdata={userdata}
|
||||
isLoggedIn={isLoggedIn}
|
||||
setIsLoggedIn={setIsLoggedIn}
|
||||
register={true}
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
setCookie={setCookie}
|
||||
cookies={cookies}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/admin/:key"
|
||||
render={(props) => (
|
||||
<Admin
|
||||
isLoggedIn={isLoggedIn}
|
||||
setIsLoggedIn={setIsLoggedIn}
|
||||
register={true}
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
setCookie={setCookie}
|
||||
cookies={cookies}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{userdata.id !== undefined ? (
|
||||
<Route
|
||||
exact
|
||||
path="/settings"
|
||||
render={(props) => (
|
||||
<SettingsPage
|
||||
isLoaded={isLoaded}
|
||||
setUserData={setUserData}
|
||||
userdata={userdata}
|
||||
globalUrl={globalUrl}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
) : null}
|
||||
<Route
|
||||
exact
|
||||
path="/AdminSetup"
|
||||
render={(props) => (
|
||||
<AdminSetup
|
||||
isLoaded={isLoaded}
|
||||
userdata={userdata}
|
||||
globalUrl={globalUrl}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/webhooks"
|
||||
render={(props) => (
|
||||
<Webhooks isLoaded={isLoaded} globalUrl={globalUrl} {...props} />
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/webhooks/:key"
|
||||
render={(props) => (
|
||||
<EditWebhook isLoaded={isLoaded} globalUrl={globalUrl} {...props} />
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/schedules"
|
||||
render={(props) => <Schedules globalUrl={globalUrl} {...props} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/dashboard"
|
||||
render={(props) => (
|
||||
<Dashboard
|
||||
isLoaded={isLoaded}
|
||||
isLoggedIn={isLoggedIn}
|
||||
globalUrl={globalUrl}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/apps/new"
|
||||
render={(props) => (
|
||||
<AppCreator
|
||||
isLoaded={isLoaded}
|
||||
isLoggedIn={isLoggedIn}
|
||||
globalUrl={globalUrl}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/apps"
|
||||
render={(props) => (
|
||||
<Apps
|
||||
isLoaded={isLoaded}
|
||||
isLoggedIn={isLoggedIn}
|
||||
globalUrl={globalUrl}
|
||||
userdata={userdata}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/apps/edit/:appid"
|
||||
render={(props) => (
|
||||
<AppCreator
|
||||
isLoaded={isLoaded}
|
||||
isLoggedIn={isLoggedIn}
|
||||
globalUrl={globalUrl}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/schedules/:key"
|
||||
render={(props) => <EditSchedule globalUrl={globalUrl} {...props} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/workflows"
|
||||
render={(props) => (
|
||||
<Workflows
|
||||
cookies={cookies}
|
||||
removeCookie={removeCookie}
|
||||
isLoaded={isLoaded}
|
||||
isLoggedIn={isLoggedIn}
|
||||
globalUrl={globalUrl}
|
||||
cookies={cookies}
|
||||
userdata={userdata}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/workflows/:key"
|
||||
render={(props) => (
|
||||
<AngularWorkflow
|
||||
userdata={userdata}
|
||||
globalUrl={globalUrl}
|
||||
isLoaded={isLoaded}
|
||||
isLoggedIn={isLoggedIn}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/docs/:key"
|
||||
render={(props) => (
|
||||
<Docs
|
||||
isMobile={isMobile}
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/docs"
|
||||
render={(props) => {
|
||||
window.location.pathname = "/docs/about";
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/introduction"
|
||||
render={(props) => (
|
||||
<Introduction
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/introduction/:key"
|
||||
render={(props) => (
|
||||
<Introduction
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/set_authentication"
|
||||
render={(props) => (
|
||||
<SetAuthentication
|
||||
userdata={userdata}
|
||||
isLoggedIn={isLoggedIn}
|
||||
setIsLoggedIn={setIsLoggedIn}
|
||||
register={true}
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
setCookie={setCookie}
|
||||
cookies={cookies}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/login_sso"
|
||||
render={(props) => (
|
||||
<SetAuthenticationSSO
|
||||
userdata={userdata}
|
||||
isLoggedIn={isLoggedIn}
|
||||
setIsLoggedIn={setIsLoggedIn}
|
||||
register={true}
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
setCookie={setCookie}
|
||||
cookies={cookies}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/"
|
||||
render={(props) => (
|
||||
<LoginPage
|
||||
isLoggedIn={isLoggedIn}
|
||||
setIsLoggedIn={setIsLoggedIn}
|
||||
register={true}
|
||||
isLoaded={isLoaded}
|
||||
globalUrl={globalUrl}
|
||||
setCookie={setCookie}
|
||||
cookies={cookies}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
// <div style={{backgroundColor: "rgba(21, 32, 43, 1)", color: "#fffff", minHeight: "100vh"}}>
|
||||
// backgroundColor: "#213243",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,3 @@
|
||||
const data = [
|
||||
{ name: "cloud", type: "cloud" },
|
||||
{ name: "onprem", type: "onprem" },
|
||||
];
|
||||
const data = [{"name": "cloud", "type": "cloud"}, {"name": "onprem", "type": "onprem"}]
|
||||
|
||||
export default data;
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
const Data = {
|
||||
src: {
|
||||
name: "Get Tickets",
|
||||
description: "Get tickets",
|
||||
outputparameters: [
|
||||
{
|
||||
name: "SymptomDescription",
|
||||
schema: { type: "string" },
|
||||
},
|
||||
{ name: "DetailedDescription", schema: { type: "string" } },
|
||||
{ name: "EventSource", schema: { type: "string" } },
|
||||
],
|
||||
},
|
||||
dst: {
|
||||
name: "Create alert",
|
||||
description: "Create alert in TheHive",
|
||||
inputparameters: [
|
||||
{
|
||||
name: "title",
|
||||
required: true,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
{ name: "description", required: true, schema: { type: "string" } },
|
||||
{ name: "source", required: true, schema: { type: "string" } },
|
||||
],
|
||||
"src": {
|
||||
"name": "Get Tickets",
|
||||
"description": "Get tickets",
|
||||
"outputparameters": [{
|
||||
"name": "SymptomDescription",
|
||||
"schema": {"type": "string"}},
|
||||
{"name": "DetailedDescription",
|
||||
"schema": {"type": "string"}},
|
||||
{"name": "EventSource",
|
||||
"schema": {"type": "string"}
|
||||
}]
|
||||
},
|
||||
"dst": {
|
||||
"name": "Create alert",
|
||||
"description": "Create alert in TheHive",
|
||||
"inputparameters": [{
|
||||
"name": "title",
|
||||
"required": true,
|
||||
"schema": {"type": "string"}},
|
||||
{"name": "description",
|
||||
"required": true,
|
||||
"schema": {"type": "string"}},
|
||||
{"name": "source",
|
||||
"required": true,
|
||||
"schema": {"type": "string"}
|
||||
}]}
|
||||
};
|
||||
|
||||
export default Data;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const data = {
|
||||
id: "8ccf0bec1fde018771ab685d2a40bd52",
|
||||
info: {
|
||||
url: "",
|
||||
name: "testing",
|
||||
description: "wut",
|
||||
"id":"8ccf0bec1fde018771ab685d2a40bd52",
|
||||
"info":{
|
||||
"url":"",
|
||||
"name":"testing",
|
||||
"description":"wut"
|
||||
},
|
||||
transforms: {},
|
||||
actions: {},
|
||||
type: "webhook",
|
||||
status: "uninitialized",
|
||||
running: false,
|
||||
};
|
||||
"transforms":{},
|
||||
"actions": {},
|
||||
"type":"webhook",
|
||||
"status":"uninitialized",
|
||||
"running":false
|
||||
}
|
||||
|
||||
export default data;
|
||||
|
||||
@@ -1,169 +1,3 @@
|
||||
const data = {
|
||||
actions: [
|
||||
{
|
||||
app_name: "hello_world",
|
||||
app_version: "1.0.0",
|
||||
errors: null,
|
||||
id: "70574332-da82-cf17-c723-75fa7b8493c2",
|
||||
is_valid: true,
|
||||
label: "hello_world",
|
||||
environment: "onprem",
|
||||
name: "hello_world",
|
||||
parameters: null,
|
||||
position: { x: 353.7438792397648, y: 260.6717930890377 },
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
app_name: "hello_world",
|
||||
app_version: "1.0.0",
|
||||
errors: null,
|
||||
id: "30522433-56ed-53c3-575d-766e282e1d3e",
|
||||
is_valid: true,
|
||||
label: "random_number",
|
||||
environment: "cloud",
|
||||
name: "random_number",
|
||||
parameters: null,
|
||||
position: { x: 458.30040774503794, y: 104.27580103487651 },
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
app_name: "hello_world",
|
||||
app_version: "1.0.0",
|
||||
errors: null,
|
||||
id: "5b7ac5b5-9514-02b9-ebe0-998c0843b104",
|
||||
is_valid: false,
|
||||
label: "hello_world_2",
|
||||
environment: "onprem",
|
||||
name: "hello_world",
|
||||
parameters: null,
|
||||
position: { x: 414.7256019053981, y: -140.46450482659628 },
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
app_name: "hello_world",
|
||||
app_version: "1.0.0",
|
||||
errors: null,
|
||||
id: "7e6e7a19-4636-cebc-91c4-052a3769a18b",
|
||||
is_valid: true,
|
||||
label: "hello_world_3",
|
||||
environment: "cloud",
|
||||
name: "hello_world",
|
||||
parameters: null,
|
||||
position: { x: 83.59752786243806, y: 50.232317715020734 },
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
app_name: "hello_world",
|
||||
app_version: "1.0.0",
|
||||
errors: null,
|
||||
id: "edbf927d-5a00-2405-28ed-47982cdf5110",
|
||||
is_valid: true,
|
||||
label: "hello_world_4",
|
||||
environment: "cloud",
|
||||
name: "hello_world",
|
||||
parameters: null,
|
||||
position: { x: -147.30681300186404, y: 89.16690830150289 },
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
app_name: "hello_world",
|
||||
app_version: "1.0.0",
|
||||
errors: null,
|
||||
id: "4844a855-1e2b-669d-fc72-5f398321ac5d",
|
||||
is_valid: false,
|
||||
label: "hello_world_5",
|
||||
environment: "onprem",
|
||||
name: "hello_world",
|
||||
parameters: null,
|
||||
position: { x: 130.24982593523967, y: 233.8325632286361 },
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
app_name: "hello_world",
|
||||
app_version: "1.0.0",
|
||||
errors: null,
|
||||
id: "6d1d3f8a-1ac9-3db4-0e0f-2fe32e9d3c09",
|
||||
is_valid: true,
|
||||
label: "hello_world_6",
|
||||
environment: "cloud",
|
||||
name: "hello_world",
|
||||
parameters: null,
|
||||
position: { x: 83.551088005629, y: -105.15867327274223 },
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
app_name: "hello_world",
|
||||
app_version: "1.0.0",
|
||||
errors: null,
|
||||
id: "469d8c2b-52ac-e397-9a29-becccd04aed8",
|
||||
is_valid: true,
|
||||
label: "hello_world_7",
|
||||
environment: "cloud",
|
||||
name: "hello_world",
|
||||
parameters: null,
|
||||
position: { x: 314.4987657226086, y: 10.167183586257954 },
|
||||
priority: 0,
|
||||
},
|
||||
],
|
||||
branches: [
|
||||
{
|
||||
destination_id: "30522433-56ed-53c3-575d-766e282e1d3e",
|
||||
id: "4bcb9795-94e6-7d5f-2074-0d5b27784e0b",
|
||||
source_id: "70574332-da82-cf17-c723-75fa7b8493c2",
|
||||
},
|
||||
{
|
||||
destination_id: "5b7ac5b5-9514-02b9-ebe0-998c0843b104",
|
||||
id: "fe0ab8e4-a535-61cd-3c09-8fd3d8e40769",
|
||||
source_id: "30522433-56ed-53c3-575d-766e282e1d3e",
|
||||
},
|
||||
{
|
||||
destination_id: "469d8c2b-52ac-e397-9a29-becccd04aed8",
|
||||
id: "8b9ee9bc-b0ab-0bb6-af61-46d4594b2663",
|
||||
source_id: "30522433-56ed-53c3-575d-766e282e1d3e",
|
||||
},
|
||||
{
|
||||
destination_id: "6d1d3f8a-1ac9-3db4-0e0f-2fe32e9d3c09",
|
||||
id: "c204d5ef-9cc1-d906-9988-86a624c57783",
|
||||
source_id: "469d8c2b-52ac-e397-9a29-becccd04aed8",
|
||||
},
|
||||
{
|
||||
destination_id: "6d1d3f8a-1ac9-3db4-0e0f-2fe32e9d3c09",
|
||||
id: "1ffb3934-60ec-8f80-5cee-3ddc0a37fdb6",
|
||||
source_id: "5b7ac5b5-9514-02b9-ebe0-998c0843b104",
|
||||
},
|
||||
{
|
||||
destination_id: "edbf927d-5a00-2405-28ed-47982cdf5110",
|
||||
id: "9c7fb048-9d0d-cb84-9ba0-be729af9b4d1",
|
||||
source_id: "6d1d3f8a-1ac9-3db4-0e0f-2fe32e9d3c09",
|
||||
},
|
||||
{
|
||||
destination_id: "edbf927d-5a00-2405-28ed-47982cdf5110",
|
||||
id: "e3ab104e-fc8b-3af5-8daa-bfa57bcf9690",
|
||||
source_id: "7e6e7a19-4636-cebc-91c4-052a3769a18b",
|
||||
},
|
||||
{
|
||||
destination_id: "7e6e7a19-4636-cebc-91c4-052a3769a18b",
|
||||
id: "b6626081-22dd-3af3-b899-480f60d886ca",
|
||||
source_id: "30522433-56ed-53c3-575d-766e282e1d3e",
|
||||
},
|
||||
{
|
||||
destination_id: "4844a855-1e2b-669d-fc72-5f398321ac5d",
|
||||
id: "4275cf97-0447-bbda-0c80-ab20d389de1a",
|
||||
source_id: "edbf927d-5a00-2405-28ed-47982cdf5110",
|
||||
},
|
||||
],
|
||||
conditions: [],
|
||||
triggers: [],
|
||||
transforms: [],
|
||||
description: "asd",
|
||||
id: "2f299808-0f1b-4ae0-97fc-ac17483dfcf7",
|
||||
id: "2f299808-0f1b-4ae0-97fc-ac17483dfcf7",
|
||||
is_valid: true,
|
||||
name: "test2",
|
||||
start: "70574332-da82-cf17-c723-75fa7b8493c2",
|
||||
owner: { username: "", id: "", orgs: "" },
|
||||
execution_org: { name: "", org: "", users: null, id: "" },
|
||||
workflow_variables: null,
|
||||
};
|
||||
const data = {"actions":[{"app_name":"hello_world","app_version":"1.0.0","errors":null,"id":"70574332-da82-cf17-c723-75fa7b8493c2","is_valid":true,"label":"hello_world","environment":"onprem","name":"hello_world","parameters":null,"position":{"x":353.7438792397648,"y":260.6717930890377},"priority":0},{"app_name":"hello_world","app_version":"1.0.0","errors":null,"id":"30522433-56ed-53c3-575d-766e282e1d3e","is_valid":true,"label":"random_number","environment":"cloud","name":"random_number","parameters":null,"position":{"x":458.30040774503794,"y":104.27580103487651},"priority":0},{"app_name":"hello_world","app_version":"1.0.0","errors":null,"id":"5b7ac5b5-9514-02b9-ebe0-998c0843b104","is_valid":false,"label":"hello_world_2","environment":"onprem","name":"hello_world","parameters":null,"position":{"x":414.7256019053981,"y":-140.46450482659628},"priority":0},{"app_name":"hello_world","app_version":"1.0.0","errors":null,"id":"7e6e7a19-4636-cebc-91c4-052a3769a18b","is_valid":true,"label":"hello_world_3","environment":"cloud","name":"hello_world","parameters":null,"position":{"x":83.59752786243806,"y":50.232317715020734},"priority":0},{"app_name":"hello_world","app_version":"1.0.0","errors":null,"id":"edbf927d-5a00-2405-28ed-47982cdf5110","is_valid":true,"label":"hello_world_4","environment":"cloud","name":"hello_world","parameters":null,"position":{"x":-147.30681300186404,"y":89.16690830150289},"priority":0},{"app_name":"hello_world","app_version":"1.0.0","errors":null,"id":"4844a855-1e2b-669d-fc72-5f398321ac5d","is_valid":false,"label":"hello_world_5","environment":"onprem","name":"hello_world","parameters":null,"position":{"x":130.24982593523967,"y":233.8325632286361},"priority":0},{"app_name":"hello_world","app_version":"1.0.0","errors":null,"id":"6d1d3f8a-1ac9-3db4-0e0f-2fe32e9d3c09","is_valid":true,"label":"hello_world_6","environment":"cloud","name":"hello_world","parameters":null,"position":{"x":83.551088005629,"y":-105.15867327274223},"priority":0},{"app_name":"hello_world","app_version":"1.0.0","errors":null,"id":"469d8c2b-52ac-e397-9a29-becccd04aed8","is_valid":true,"label":"hello_world_7","environment":"cloud","name":"hello_world","parameters":null,"position":{"x":314.4987657226086,"y":10.167183586257954},"priority":0}],"branches":[{"destination_id":"30522433-56ed-53c3-575d-766e282e1d3e","id":"4bcb9795-94e6-7d5f-2074-0d5b27784e0b","source_id":"70574332-da82-cf17-c723-75fa7b8493c2"},{"destination_id":"5b7ac5b5-9514-02b9-ebe0-998c0843b104","id":"fe0ab8e4-a535-61cd-3c09-8fd3d8e40769","source_id":"30522433-56ed-53c3-575d-766e282e1d3e"},{"destination_id":"469d8c2b-52ac-e397-9a29-becccd04aed8","id":"8b9ee9bc-b0ab-0bb6-af61-46d4594b2663","source_id":"30522433-56ed-53c3-575d-766e282e1d3e"},{"destination_id":"6d1d3f8a-1ac9-3db4-0e0f-2fe32e9d3c09","id":"c204d5ef-9cc1-d906-9988-86a624c57783","source_id":"469d8c2b-52ac-e397-9a29-becccd04aed8"},{"destination_id":"6d1d3f8a-1ac9-3db4-0e0f-2fe32e9d3c09","id":"1ffb3934-60ec-8f80-5cee-3ddc0a37fdb6","source_id":"5b7ac5b5-9514-02b9-ebe0-998c0843b104"},{"destination_id":"edbf927d-5a00-2405-28ed-47982cdf5110","id":"9c7fb048-9d0d-cb84-9ba0-be729af9b4d1","source_id":"6d1d3f8a-1ac9-3db4-0e0f-2fe32e9d3c09"},{"destination_id":"edbf927d-5a00-2405-28ed-47982cdf5110","id":"e3ab104e-fc8b-3af5-8daa-bfa57bcf9690","source_id":"7e6e7a19-4636-cebc-91c4-052a3769a18b"},{"destination_id":"7e6e7a19-4636-cebc-91c4-052a3769a18b","id":"b6626081-22dd-3af3-b899-480f60d886ca","source_id":"30522433-56ed-53c3-575d-766e282e1d3e"},{"destination_id":"4844a855-1e2b-669d-fc72-5f398321ac5d","id":"4275cf97-0447-bbda-0c80-ab20d389de1a","source_id":"edbf927d-5a00-2405-28ed-47982cdf5110"}],"conditions":[],"triggers":[],"transforms":[],"description":"asd","id":"2f299808-0f1b-4ae0-97fc-ac17483dfcf7","id":"2f299808-0f1b-4ae0-97fc-ac17483dfcf7","is_valid":true,"name":"test2","start":"70574332-da82-cf17-c723-75fa7b8493c2","owner":{"username":"","id":"","orgs":""},"execution_org":{"name":"","org":"","users":null,"id":""},"workflow_variables":null}
|
||||
|
||||
export default data;
|
||||
|
||||
+68
-68
@@ -23,7 +23,7 @@
|
||||
let chart1_2_options = {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false,
|
||||
display: false
|
||||
},
|
||||
tooltips: {
|
||||
backgroundColor: "#f5f5f5",
|
||||
@@ -33,7 +33,7 @@ let chart1_2_options = {
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest",
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
@@ -43,15 +43,15 @@ let chart1_2_options = {
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: "rgba(29,140,248,0.0)",
|
||||
zeroLineColor: "transparent",
|
||||
zeroLineColor: "transparent"
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 60,
|
||||
suggestedMax: 125,
|
||||
padding: 20,
|
||||
fontColor: "#9a9a9a",
|
||||
},
|
||||
},
|
||||
fontColor: "#9a9a9a"
|
||||
}
|
||||
}
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
@@ -59,22 +59,22 @@ let chart1_2_options = {
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: "rgba(29,140,248,0.1)",
|
||||
zeroLineColor: "transparent",
|
||||
zeroLineColor: "transparent"
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#9a9a9a",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
fontColor: "#9a9a9a"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// #########################################
|
||||
// // // used inside src/views/Dashboard.js
|
||||
// #########################################
|
||||
let chartExample1 = {
|
||||
data1: (canvas) => {
|
||||
data1: canvas => {
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);
|
||||
@@ -96,7 +96,7 @@ let chartExample1 = {
|
||||
"SEP",
|
||||
"OCT",
|
||||
"NOV",
|
||||
"DEC",
|
||||
"DEC"
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
@@ -114,12 +114,12 @@ let chartExample1 = {
|
||||
pointHoverRadius: 4,
|
||||
pointHoverBorderWidth: 15,
|
||||
pointRadius: 4,
|
||||
data: [100, 70, 90, 70, 85, 60, 75, 60, 90, 80, 110, 100],
|
||||
},
|
||||
],
|
||||
data: [100, 70, 90, 70, 85, 60, 75, 60, 90, 80, 110, 100]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
data2: (canvas) => {
|
||||
data2: canvas => {
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);
|
||||
@@ -141,7 +141,7 @@ let chartExample1 = {
|
||||
"SEP",
|
||||
"OCT",
|
||||
"NOV",
|
||||
"DEC",
|
||||
"DEC"
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
@@ -159,12 +159,12 @@ let chartExample1 = {
|
||||
pointHoverRadius: 4,
|
||||
pointHoverBorderWidth: 15,
|
||||
pointRadius: 4,
|
||||
data: [80, 120, 105, 110, 95, 105, 90, 100, 80, 95, 70, 120],
|
||||
},
|
||||
],
|
||||
data: [80, 120, 105, 110, 95, 105, 90, 100, 80, 95, 70, 120]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
data3: (canvas) => {
|
||||
data3: canvas => {
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);
|
||||
@@ -186,7 +186,7 @@ let chartExample1 = {
|
||||
"SEP",
|
||||
"OCT",
|
||||
"NOV",
|
||||
"DEC",
|
||||
"DEC"
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
@@ -204,19 +204,19 @@ let chartExample1 = {
|
||||
pointHoverRadius: 4,
|
||||
pointHoverBorderWidth: 15,
|
||||
pointRadius: 4,
|
||||
data: [60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130],
|
||||
},
|
||||
],
|
||||
data: [60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
options: chart1_2_options,
|
||||
options: chart1_2_options
|
||||
};
|
||||
|
||||
// #########################################
|
||||
// // // used inside src/views/Dashboard.js
|
||||
// #########################################
|
||||
let chartExample2 = {
|
||||
data: (canvas) => {
|
||||
data: canvas => {
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);
|
||||
@@ -243,19 +243,19 @@ let chartExample2 = {
|
||||
pointHoverRadius: 4,
|
||||
pointHoverBorderWidth: 15,
|
||||
pointRadius: 4,
|
||||
data: [80, 100, 70, 80, 120, 80],
|
||||
},
|
||||
],
|
||||
data: [80, 100, 70, 80, 120, 80]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
options: chart1_2_options,
|
||||
options: chart1_2_options
|
||||
};
|
||||
|
||||
// #########################################
|
||||
// // // used inside src/views/Dashboard.js
|
||||
// #########################################
|
||||
let chartExample3 = {
|
||||
data: (canvas) => {
|
||||
data: canvas => {
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);
|
||||
@@ -276,15 +276,15 @@ let chartExample3 = {
|
||||
borderWidth: 2,
|
||||
borderDash: [],
|
||||
borderDashOffset: 0.0,
|
||||
data: [53, 20, 10, 80, 100, 45],
|
||||
},
|
||||
],
|
||||
data: [53, 20, 10, 80, 100, 45]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false,
|
||||
display: false
|
||||
},
|
||||
tooltips: {
|
||||
backgroundColor: "#f5f5f5",
|
||||
@@ -294,7 +294,7 @@ let chartExample3 = {
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest",
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
@@ -303,38 +303,38 @@ let chartExample3 = {
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: "rgba(225,78,202,0.1)",
|
||||
zeroLineColor: "transparent",
|
||||
zeroLineColor: "transparent"
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 60,
|
||||
suggestedMax: 120,
|
||||
padding: 20,
|
||||
fontColor: "#9e9e9e",
|
||||
},
|
||||
},
|
||||
fontColor: "#9e9e9e"
|
||||
}
|
||||
}
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: "rgba(225,78,202,0.1)",
|
||||
zeroLineColor: "transparent",
|
||||
zeroLineColor: "transparent"
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#9e9e9e",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
fontColor: "#9e9e9e"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// #########################################
|
||||
// // // used inside src/views/Dashboard.js
|
||||
// #########################################
|
||||
const chartExample4 = {
|
||||
data: (canvas) => {
|
||||
data: canvas => {
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);
|
||||
@@ -361,15 +361,15 @@ const chartExample4 = {
|
||||
pointHoverRadius: 4,
|
||||
pointHoverBorderWidth: 15,
|
||||
pointRadius: 4,
|
||||
data: [90, 27, 60, 12, 80],
|
||||
},
|
||||
],
|
||||
data: [90, 27, 60, 12, 80]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false,
|
||||
display: false
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
@@ -380,7 +380,7 @@ const chartExample4 = {
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest",
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
@@ -390,15 +390,15 @@ const chartExample4 = {
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: "rgba(29,140,248,0.0)",
|
||||
zeroLineColor: "transparent",
|
||||
zeroLineColor: "transparent"
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 50,
|
||||
suggestedMax: 125,
|
||||
padding: 20,
|
||||
fontColor: "#9e9e9e",
|
||||
},
|
||||
},
|
||||
fontColor: "#9e9e9e"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
xAxes: [
|
||||
@@ -407,21 +407,21 @@ const chartExample4 = {
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: "rgba(0,242,195,0.1)",
|
||||
zeroLineColor: "transparent",
|
||||
zeroLineColor: "transparent"
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#9e9e9e",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
fontColor: "#9e9e9e"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
chartExample1, // in src/views/Dashboard.js
|
||||
chartExample2, // in src/views/Dashboard.js
|
||||
chartExample3, // in src/views/Dashboard.js
|
||||
chartExample4, // in src/views/Dashboard.js
|
||||
chartExample4 // in src/views/Dashboard.js
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect} from 'react';
|
||||
|
||||
const Popup = (props) => {
|
||||
const { data } = props;
|
||||
@@ -9,11 +9,18 @@ const Popup = (props) => {
|
||||
height: "50px",
|
||||
backgroundColor: "black",
|
||||
color: "white",
|
||||
};
|
||||
}
|
||||
|
||||
const popupData = <div>HEY</div>;
|
||||
const popupData =
|
||||
<div>
|
||||
HEY
|
||||
</div>
|
||||
|
||||
return <div>{popupData}</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
{popupData}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Popup;
|
||||
export default Popup
|
||||
|
||||
@@ -1,48 +1,46 @@
|
||||
import React from "react";
|
||||
import InfoIcon from "@material-ui/icons/Info";
|
||||
import CheckIcon from "@material-ui/icons/Check";
|
||||
import ErrorOutlineIcon from "@material-ui/icons/ErrorOutline";
|
||||
import CloseIcon from "@material-ui/icons/Close";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import React from 'react'
|
||||
import InfoIcon from '@material-ui/icons/Info';
|
||||
import CheckIcon from '@material-ui/icons/Check';
|
||||
import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
|
||||
import CloseIcon from '@material-ui/icons/Close';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
||||
const alertStyle = {
|
||||
backgroundColor: "rgba(0,0,0,0.9)",
|
||||
color: "white",
|
||||
backgroundColor: 'rgba(0,0,0,0.9)',
|
||||
color: 'white',
|
||||
padding: 15,
|
||||
textTransform: "uppercase",
|
||||
borderRadius: "3px",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
boxShadow: "0px 2px 2px 2px rgba(0, 0, 0, 0.03)",
|
||||
textTransform: 'uppercase',
|
||||
borderRadius: '3px',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
boxShadow: '0px 2px 2px 2px rgba(0, 0, 0, 0.03)',
|
||||
width: 300,
|
||||
boxSizing: "border-box",
|
||||
boxSizing: 'border-box',
|
||||
zIndex: 100001,
|
||||
overflow: "hidden",
|
||||
};
|
||||
}
|
||||
|
||||
const buttonStyle = {
|
||||
marginLeft: "20px",
|
||||
border: "none",
|
||||
backgroundColor: "transparent",
|
||||
cursor: "pointer",
|
||||
color: "#FFFFFF",
|
||||
};
|
||||
marginLeft: '20px',
|
||||
border: 'none',
|
||||
backgroundColor: 'transparent',
|
||||
cursor: 'pointer',
|
||||
color: '#FFFFFF'
|
||||
}
|
||||
|
||||
const AlertTemplate = ({ message, options, style, close }) => {
|
||||
return (
|
||||
<div style={{ ...alertStyle, ...style }}>
|
||||
{options.type === "info" && <InfoIcon style={{ color: "white" }} />}
|
||||
{options.type === "success" && <CheckIcon style={{ color: "green" }} />}
|
||||
{options.type === "error" && (
|
||||
<ErrorOutlineIcon style={{ color: "red" }} />
|
||||
)}
|
||||
<Typography style={{ marginLeft: 15, flex: 2 }}>{message}</Typography>
|
||||
{options.type === 'info' && <InfoIcon style={{color: "white"}} />}
|
||||
{options.type === 'success' && <CheckIcon style={{color: "green", }}/>}
|
||||
{options.type === 'error' && <ErrorOutlineIcon style={{color: "red"}} />}
|
||||
<Typography style={{marginLeft: 15, flex: 2 }}>{message}</Typography>
|
||||
<button onClick={close} style={buttonStyle}>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default AlertTemplate;
|
||||
export default AlertTemplate
|
||||
|
||||
@@ -1,20 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
import React, {useState} from 'react';
|
||||
|
||||
import {
|
||||
InputAdornment,
|
||||
Tooltip,
|
||||
TextField,
|
||||
CircularProgress,
|
||||
ButtonGroup,
|
||||
Button,
|
||||
Avatar,
|
||||
ListItemAvatar,
|
||||
Typography,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
} from "@material-ui/core";
|
||||
import { FavoriteBorder as FavoriteBorderIcon } from "@material-ui/icons";
|
||||
import { InputAdornment, Tooltip, TextField, CircularProgress, ButtonGroup, Button, Avatar, ListItemAvatar, Typography, List, ListItem, ListItemText} from '@material-ui/core';
|
||||
import {FavoriteBorder as FavoriteBorderIcon} from '@material-ui/icons';
|
||||
import { FixName } from "../views/Apps.jsx";
|
||||
|
||||
// Handles workflow updates on first open to highlight the issues of the workflow
|
||||
@@ -25,49 +12,31 @@ import { FixName } from "../views/Apps.jsx";
|
||||
//
|
||||
// Specifically used for UNSAVED workflows only?
|
||||
const ConfigureWorkflow = (props) => {
|
||||
const {
|
||||
globalUrl,
|
||||
theme,
|
||||
workflow,
|
||||
appAuthentication,
|
||||
setSelectedAction,
|
||||
setAuthenticationModalOpen,
|
||||
setSelectedApp,
|
||||
apps,
|
||||
selectedAction,
|
||||
setConfigureWorkflowModalOpen,
|
||||
saveWorkflow,
|
||||
newWebhook,
|
||||
submitSchedule,
|
||||
referenceUrl,
|
||||
isCloud,
|
||||
setAuthenticationType,
|
||||
alert,
|
||||
} = props;
|
||||
const [requiredActions, setRequiredActions] = React.useState([]);
|
||||
const [requiredVariables, setRequiredVariables] = React.useState([]);
|
||||
const [requiredTriggers, setRequiredTriggers] = React.useState([]);
|
||||
const [previousAuth, setPreviousAuth] = React.useState(appAuthentication);
|
||||
const [firstLoad, setFirstLoad] = React.useState("");
|
||||
const [itemChanged, setItemChanged] = React.useState(false);
|
||||
var finished = false;
|
||||
const { globalUrl, theme, workflow, appAuthentication, setSelectedAction, setAuthenticationModalOpen, setSelectedApp, apps, selectedAction,setConfigureWorkflowModalOpen, saveWorkflow, newWebhook, submitSchedule, referenceUrl, isCloud, setAuthenticationType, alert, } = props
|
||||
const [requiredActions, setRequiredActions] = React.useState([])
|
||||
const [requiredVariables, setRequiredVariables] = React.useState([])
|
||||
const [requiredTriggers, setRequiredTriggers] = React.useState([])
|
||||
const [previousAuth, setPreviousAuth] = React.useState(appAuthentication)
|
||||
const [firstLoad, setFirstLoad] = React.useState("")
|
||||
const [itemChanged, setItemChanged] = React.useState(false)
|
||||
var finished = false
|
||||
|
||||
if (workflow === undefined || workflow === null) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
if (apps === undefined || apps === null) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
if (appAuthentication === undefined || appAuthentication === null) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
const getApp = (actionId, appId) => {
|
||||
fetch(globalUrl + "/api/v1/apps/" + appId + "/config?openapi=false", {
|
||||
fetch(globalUrl+"/api/v1/apps/"+appId+"/config?openapi=false", {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
@@ -75,230 +44,181 @@ const ConfigureWorkflow = (props) => {
|
||||
if (response.status === 200) {
|
||||
//alert.success("Successfully GOT app "+appId)
|
||||
} else {
|
||||
alert.error("Failed getting app");
|
||||
alert.error("Failed getting app")
|
||||
}
|
||||
|
||||
return response.json();
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
console.log("ACTION: ", responseJson);
|
||||
if (
|
||||
responseJson.actions !== undefined &&
|
||||
responseJson.actions !== null
|
||||
) {
|
||||
console.log("ACTION: ", responseJson)
|
||||
if (responseJson.actions !== undefined && responseJson.actions !== null) {
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
alert.error(error.toString());
|
||||
.catch(error => {
|
||||
alert.error(error.toString())
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (firstLoad.length === 0 || firstLoad !== workflow.id) {
|
||||
if (finished) {
|
||||
setConfigureWorkflowModalOpen(false);
|
||||
return null;
|
||||
setConfigureWorkflowModalOpen(false)
|
||||
return null
|
||||
}
|
||||
|
||||
if (apps === undefined || apps === null || apps.length === 0) {
|
||||
console.log("No apps loaded: ", apps);
|
||||
setConfigureWorkflowModalOpen(false);
|
||||
return null;
|
||||
console.log("No apps loaded: ", apps)
|
||||
setConfigureWorkflowModalOpen(false)
|
||||
return null
|
||||
}
|
||||
|
||||
setFirstLoad(workflow.id);
|
||||
const newactions = [];
|
||||
setFirstLoad(workflow.id)
|
||||
const newactions = []
|
||||
for (var key in workflow.actions) {
|
||||
const action = workflow.actions[key];
|
||||
const action = workflow.actions[key]
|
||||
var newaction = {
|
||||
large_image: action.large_image,
|
||||
app_name: action.app_name,
|
||||
app_version: action.app_version,
|
||||
activation_done: false,
|
||||
must_activate: false,
|
||||
must_authenticate: false,
|
||||
auth_done: false,
|
||||
action_ids: [],
|
||||
action: action,
|
||||
app: {},
|
||||
};
|
||||
"large_image": action.large_image,
|
||||
"app_name": action.app_name,
|
||||
"app_version": action.app_version,
|
||||
"activation_done": false,
|
||||
"must_activate": false,
|
||||
"must_authenticate": false,
|
||||
"auth_done": false,
|
||||
"action_ids": [],
|
||||
"action": action,
|
||||
"app": {},
|
||||
}
|
||||
|
||||
const app = apps.find(
|
||||
(app) =>
|
||||
app.name === action.app_name &&
|
||||
(app.app_version === action.app_version ||
|
||||
(app.loop_versions !== null &&
|
||||
app.loop_versions.includes(action.app_version)))
|
||||
);
|
||||
const app = apps.find(app => app.name === action.app_name && (app.app_version === action.app_version || (app.loop_versions !== null && app.loop_versions.includes(action.app_version))))
|
||||
if (app === undefined || app === null) {
|
||||
console.log("App not found: ", action.app_name);
|
||||
console.log("App not found: ", action.app_name)
|
||||
|
||||
newaction.must_activate = true;
|
||||
newaction.must_activate = true
|
||||
} else {
|
||||
if (
|
||||
action.authentication_id === "" &&
|
||||
app.authentication.required === true
|
||||
) {
|
||||
if (action.authentication_id === "" && app.authentication.required === true) {
|
||||
// Check if configuration is filled or not
|
||||
var filled = true;
|
||||
var filled = true
|
||||
for (var key in action.parameters) {
|
||||
if (action.parameters[key].configuration) {
|
||||
//console.log("Found config: ", action.parameters[key])
|
||||
if (
|
||||
action.parameters[key].value === null ||
|
||||
action.parameters[key].value.length === 0
|
||||
) {
|
||||
filled = false;
|
||||
break;
|
||||
if (action.parameters[key].value === null || action.parameters[key].value.length === 0) {
|
||||
filled = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!filled) {
|
||||
newaction.must_authenticate = true;
|
||||
newaction.action_ids.push(action.id);
|
||||
newaction.must_authenticate = true
|
||||
newaction.action_ids.push(action.id)
|
||||
}
|
||||
}
|
||||
|
||||
newaction.app = app;
|
||||
newaction.app = app
|
||||
}
|
||||
|
||||
if (
|
||||
action.errors !== undefined &&
|
||||
action.errors !== null &&
|
||||
action.errors.length > 0
|
||||
) {
|
||||
if (action.errors !== undefined && action.errors !== null && action.errors.length > 0) {
|
||||
//console.log("Node has errors!: ", action.errors)
|
||||
}
|
||||
|
||||
if (newaction.must_authenticate) {
|
||||
var authenticationOptions = [];
|
||||
var authenticationOptions = []
|
||||
for (var key in appAuthentication) {
|
||||
const auth = appAuthentication[key];
|
||||
const auth = appAuthentication[key]
|
||||
if (auth.app.name === app.name && auth.active) {
|
||||
//console.log("Found auth: ", auth)
|
||||
authenticationOptions.push(auth);
|
||||
newaction.authenticationId = auth.id;
|
||||
break;
|
||||
authenticationOptions.push(auth)
|
||||
newaction.authenticationId = auth.id
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
newaction.authenticationId === null ||
|
||||
newaction.authenticationId === undefined ||
|
||||
newaction.authenticationId.length === ""
|
||||
) {
|
||||
if (newaction.authenticationId === null || newaction.authenticationId === undefined || newaction.authenticationId.length === "") {
|
||||
//console.log("FAILED to authenticate node!")
|
||||
|
||||
if (
|
||||
newactions.find(
|
||||
(tmpaction) =>
|
||||
tmpaction.app_id === newaction.app_id &&
|
||||
tmpaction.app_name === newaction.app_name
|
||||
) !== undefined
|
||||
) {
|
||||
console.log("Action already found.");
|
||||
if (newactions.find(tmpaction => tmpaction.app_id === newaction.app_id && tmpaction.app_name === newaction.app_name) !== undefined) {
|
||||
console.log("Action already found.")
|
||||
} else {
|
||||
newactions.push(newaction);
|
||||
newactions.push(newaction)
|
||||
}
|
||||
} else {
|
||||
//console.log("Skipping node as it's already authenticated.")
|
||||
newaction.authentication = authenticationOptions;
|
||||
workflow.actions[key] = newaction;
|
||||
newaction.authentication = authenticationOptions
|
||||
workflow.actions[key] = newaction
|
||||
}
|
||||
} else if (newaction.must_activate) {
|
||||
if (
|
||||
newactions.find(
|
||||
(tmpaction) =>
|
||||
tmpaction.app_id === newaction.app_id &&
|
||||
tmpaction.app_name === newaction.app_name
|
||||
) !== undefined
|
||||
) {
|
||||
console.log("Action already found.");
|
||||
|
||||
if (newactions.find(tmpaction => tmpaction.app_id === newaction.app_id && tmpaction.app_name === newaction.app_name) !== undefined) {
|
||||
console.log("Action already found.")
|
||||
} else {
|
||||
newactions.push(newaction);
|
||||
newactions.push(newaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var key in workflow.workflow_variables) {
|
||||
const variable = workflow.workflow_variables[key];
|
||||
if (
|
||||
variable.value === undefined ||
|
||||
variable.value === undefined ||
|
||||
variable.value.length < 2
|
||||
) {
|
||||
variable.value = "";
|
||||
variable.index = key;
|
||||
requiredVariables.push(variable);
|
||||
const variable = workflow.workflow_variables[key]
|
||||
if (variable.value === undefined || variable.value === undefined || variable.value.length < 2) {
|
||||
variable.value = ""
|
||||
variable.index = key
|
||||
requiredVariables.push(variable)
|
||||
}
|
||||
}
|
||||
|
||||
for (var key in workflow.triggers) {
|
||||
var trigger = workflow.triggers[key];
|
||||
trigger.index = key;
|
||||
var trigger = workflow.triggers[key]
|
||||
trigger.index = key
|
||||
|
||||
if (trigger.status === "running") {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
if (
|
||||
trigger.trigger_type === "SUBFLOW" ||
|
||||
trigger.trigger_type === "USERINPUT"
|
||||
) {
|
||||
continue;
|
||||
if (trigger.trigger_type === "SUBFLOW" || trigger.trigger_type === "USERINPUT") {
|
||||
continue
|
||||
}
|
||||
|
||||
requiredTriggers.push(trigger);
|
||||
requiredTriggers.push(trigger)
|
||||
}
|
||||
|
||||
if (
|
||||
requiredTriggers.length === 0 &&
|
||||
requiredVariables.length === 0 &&
|
||||
newactions.length === 0
|
||||
) {
|
||||
setConfigureWorkflowModalOpen(false);
|
||||
if (requiredTriggers.length === 0 && requiredVariables.length === 0 && newactions.length === 0) {
|
||||
setConfigureWorkflowModalOpen(false)
|
||||
}
|
||||
|
||||
setRequiredTriggers(requiredTriggers);
|
||||
setRequiredVariables(requiredVariables);
|
||||
setRequiredActions(newactions);
|
||||
setRequiredTriggers(requiredTriggers)
|
||||
setRequiredVariables(requiredVariables)
|
||||
setRequiredActions(newactions)
|
||||
}
|
||||
|
||||
if (appAuthentication.length !== previousAuth.length) {
|
||||
var newactions = [];
|
||||
var newactions = []
|
||||
for (var actionkey in requiredActions) {
|
||||
var newaction = requiredActions[actionkey];
|
||||
const app = newaction.app;
|
||||
var newaction = requiredActions[actionkey]
|
||||
const app = newaction.app
|
||||
|
||||
for (var key in appAuthentication) {
|
||||
const auth = appAuthentication[key];
|
||||
const auth = appAuthentication[key]
|
||||
if (auth.app.name === app.name && auth.active) {
|
||||
newaction.auth_done = true;
|
||||
break;
|
||||
newaction.auth_done = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
newactions.push(newaction);
|
||||
newactions.push(newaction)
|
||||
}
|
||||
|
||||
setRequiredActions(newactions);
|
||||
setPreviousAuth(appAuthentication);
|
||||
setRequiredActions(newactions)
|
||||
setPreviousAuth(appAuthentication)
|
||||
// Set auth done to true
|
||||
//"auth_done": false
|
||||
}
|
||||
|
||||
const TriggerSection = (props) => {
|
||||
const { trigger } = props;
|
||||
const {trigger} = props
|
||||
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar variant="rounded">
|
||||
<img
|
||||
alt={trigger.label}
|
||||
src={trigger.large_image}
|
||||
style={{ width: 50 }}
|
||||
/>
|
||||
<img alt={trigger.label} src={trigger.large_image} style={{width: 50}} />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
@@ -306,56 +226,41 @@ const ConfigureWorkflow = (props) => {
|
||||
secondary={trigger.description}
|
||||
style={{}}
|
||||
/>
|
||||
{trigger.trigger_type === "WEBHOOK" && trigger.status !== "running" ? (
|
||||
<Button
|
||||
disabled={trigger.status === "running"}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
workflow.triggers[trigger.index].status = "running";
|
||||
{trigger.trigger_type === "WEBHOOK" && trigger.status !== "running" ?
|
||||
<Button disabled={trigger.status === "running"} color="primary" variant="contained" onClick={() => {
|
||||
workflow.triggers[trigger.index].status = "running"
|
||||
if (workflow.triggers[trigger.index].parameters === null) {
|
||||
workflow.triggers[trigger.index].parameters = [
|
||||
{
|
||||
name: "url",
|
||||
value: referenceUrl + "webhook_" + trigger.id,
|
||||
},
|
||||
{ name: "tmp", value: "webhook_" + trigger.id },
|
||||
];
|
||||
{"name": "url", "value": referenceUrl+"webhook_"+trigger.id},
|
||||
{"name": "tmp", "value": "webhook_"+trigger.id},
|
||||
]
|
||||
}
|
||||
|
||||
newWebhook(workflow.triggers[trigger.index]);
|
||||
saveWorkflow(workflow);
|
||||
setItemChanged(true);
|
||||
}}
|
||||
>
|
||||
newWebhook(workflow.triggers[trigger.index])
|
||||
saveWorkflow(workflow)
|
||||
setItemChanged(true)
|
||||
}}>
|
||||
{trigger.status !== "running" ? "Start" : "Running"}
|
||||
</Button>
|
||||
) : trigger.trigger_type === "SCHEDULE" &&
|
||||
trigger.status !== "running" ? (
|
||||
<Button
|
||||
disabled={trigger.status === "running"}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
workflow.triggers[trigger.index].status = "running";
|
||||
:
|
||||
trigger.trigger_type === "SCHEDULE" && trigger.status !== "running" ?
|
||||
<Button disabled={trigger.status === "running"} color="primary" variant="contained" onClick={() => {
|
||||
workflow.triggers[trigger.index].status = "running"
|
||||
if (workflow.triggers[trigger.index].parameters === null) {
|
||||
workflow.triggers[trigger.index].parameters = [
|
||||
{ name: "cron", value: isCloud ? "*/15 * * * *" : "120" },
|
||||
{
|
||||
name: "execution_argument",
|
||||
value: '{"example": {"json": "is cool"}}',
|
||||
},
|
||||
];
|
||||
{"name": "cron", "value": isCloud ? "*/15 * * * *" : "120"},
|
||||
{"name": "execution_argument", "value": '{"example": {"json": "is cool"}}'},
|
||||
]
|
||||
}
|
||||
|
||||
submitSchedule(workflow.triggers[trigger.index], trigger.index);
|
||||
saveWorkflow(workflow);
|
||||
setItemChanged(true);
|
||||
}}
|
||||
>
|
||||
submitSchedule(workflow.triggers[trigger.index], trigger.index)
|
||||
saveWorkflow(workflow)
|
||||
setItemChanged(true)
|
||||
}}>
|
||||
{trigger.status !== "running" ? "Start" : "Running"}
|
||||
</Button>
|
||||
) : null}
|
||||
:
|
||||
null}
|
||||
{/*
|
||||
<ListItemText
|
||||
primary={
|
||||
@@ -390,11 +295,11 @@ const ConfigureWorkflow = (props) => {
|
||||
/>
|
||||
*/}
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const VariableSection = (props) => {
|
||||
const { variable } = props;
|
||||
const {variable} = props
|
||||
|
||||
//<Typography variant="body2">Name: {variable.name} - {variable.value}. </Typography>
|
||||
return (
|
||||
@@ -412,55 +317,46 @@ const ConfigureWorkflow = (props) => {
|
||||
<ListItemText
|
||||
primary={
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: 5,
|
||||
}}
|
||||
style={{backgroundColor: theme.palette.inputColor, borderRadius: 5,}}
|
||||
InputProps={{
|
||||
style: {
|
||||
style:{
|
||||
color: "white",
|
||||
minHeight: 50,
|
||||
marginLeft: 5,
|
||||
maxWidth: "95%",
|
||||
fontSize: "1em",
|
||||
},
|
||||
endAdornment: <InputAdornment position="end"></InputAdornment>,
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
fullWidth
|
||||
color="primary"
|
||||
type={"text"}
|
||||
placeholder={`New value for ${variable.name}`}
|
||||
onChange={(event) => {
|
||||
console.log(
|
||||
"NEW VALUE ON INDEX",
|
||||
variable.index,
|
||||
variable.value
|
||||
);
|
||||
console.log("NEW VALUE ON INDEX", variable.index, variable.value)
|
||||
}}
|
||||
onBlur={(event) => {
|
||||
workflow.workflow_variables[variable.index].value =
|
||||
event.target.value;
|
||||
workflow.workflow_variables[variable.index].value = event.target.value
|
||||
}}
|
||||
/>
|
||||
}
|
||||
style={{}}
|
||||
/>
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const AppSection = (props) => {
|
||||
const { action } = props;
|
||||
const {action} = props
|
||||
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar variant="rounded">
|
||||
<img
|
||||
alt={action.app_name}
|
||||
src={action.large_image}
|
||||
style={{ width: 50 }}
|
||||
/>
|
||||
<img alt={action.app_name} src={action.large_image} style={{width: 50}} />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
@@ -468,90 +364,76 @@ const ConfigureWorkflow = (props) => {
|
||||
secondary={action.app_version}
|
||||
style={{}}
|
||||
/>
|
||||
{action.must_authenticate ? (
|
||||
action.auth_done ? (
|
||||
{action.must_authenticate ?
|
||||
action.auth_done ?
|
||||
<Button color="primary" variant="outlined" onClick={() => {}}>
|
||||
Authenticated
|
||||
</Button>
|
||||
) : selectedAction.app_name === action.app_name ? (
|
||||
:
|
||||
selectedAction.app_name === action.app_name ?
|
||||
<CircularProgress />
|
||||
) : (
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setAuthenticationType(
|
||||
action.app.authentication.type === "oauth2" &&
|
||||
action.app.authentication.redirect_uri !== undefined &&
|
||||
action.app.authentication.redirect_uri !== null
|
||||
? {
|
||||
type: "oauth2",
|
||||
redirect_uri: action.app.authentication.redirect_uri,
|
||||
token_uri: action.app.authentication.token_uri,
|
||||
scope: action.app.authentication.scope,
|
||||
:
|
||||
<Button color="primary" variant="contained" onClick={() => {
|
||||
setAuthenticationType(action.app.authentication.type === "oauth2" && action.app.authentication.redirect_uri !== undefined && action.app.authentication.redirect_uri !== null ?
|
||||
{
|
||||
"type": "oauth2",
|
||||
"redirect_uri": action.app.authentication.redirect_uri,
|
||||
"token_uri": action.app.authentication.token_uri,
|
||||
"scope": action.app.authentication.scope,
|
||||
} : {
|
||||
"type": ""
|
||||
}
|
||||
: {
|
||||
type: "",
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
setItemChanged(true);
|
||||
setSelectedAction(action.action);
|
||||
setSelectedApp(action.app);
|
||||
setAuthenticationModalOpen(true);
|
||||
}}
|
||||
>
|
||||
setItemChanged(true)
|
||||
setSelectedAction(action.action)
|
||||
setSelectedApp(action.app)
|
||||
setAuthenticationModalOpen(true)
|
||||
}}>
|
||||
Authenticate
|
||||
</Button>
|
||||
)
|
||||
) : null}
|
||||
{action.must_activate ? (
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
activateApp(action.app_id, action.app_name, action.app_version);
|
||||
setItemChanged(true);
|
||||
}}
|
||||
>
|
||||
:
|
||||
null}
|
||||
{action.must_activate ?
|
||||
<Button color="primary" variant="contained" onClick={() => {
|
||||
activateApp(action.app_id, action.app_name, action.app_version)
|
||||
setItemChanged(true)
|
||||
}}>
|
||||
Activate
|
||||
</Button>
|
||||
) : null}
|
||||
: null}
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const activateApp = (app_id, app_name, app_version) => {
|
||||
fetch(
|
||||
`${globalUrl}/api/v1/apps/app_id/activate?app_name=${app_name}&app_version=${app_version}`,
|
||||
{
|
||||
method: "GET",
|
||||
fetch(`${globalUrl}/api/v1/apps/app_id/activate?app_name=${app_name}&app_version=${app_version}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
}
|
||||
)
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
//window.location.pathname = "/search"
|
||||
//alert.error("Failed to find this app. Is it public?")
|
||||
}
|
||||
|
||||
return response.json();
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success === false) {
|
||||
alert.error("Failed to activate the app");
|
||||
alert.error("Failed to activate the app")
|
||||
} else {
|
||||
alert.success("App activated for your organization!");
|
||||
alert.success("App activated for your organization!")
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
alert.error(error.toString());
|
||||
.catch(error => {
|
||||
alert.error(error.toString())
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -559,46 +441,47 @@ const ConfigureWorkflow = (props) => {
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
The following configuration makes the workflow ready immediately.
|
||||
</Typography>
|
||||
{requiredActions.length > 0 ? (
|
||||
{requiredActions.length > 0 ?
|
||||
<span>
|
||||
<Typography variant="body1" style={{ marginTop: 10 }}>
|
||||
Actions
|
||||
</Typography>
|
||||
<Typography variant="body1" style={{marginTop: 10}}>Actions</Typography>
|
||||
<List>
|
||||
{requiredActions.map((data, index) => {
|
||||
return <AppSection key={index} action={data} />;
|
||||
return (
|
||||
<AppSection key={index} action={data} />
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</span>
|
||||
) : null}
|
||||
: null}
|
||||
|
||||
{requiredVariables.length > 0 ? (
|
||||
{requiredVariables.length > 0 ?
|
||||
<span>
|
||||
<Typography variant="body1" style={{ marginTop: 10 }}>
|
||||
Variables
|
||||
</Typography>
|
||||
<Typography variant="body1" style={{marginTop: 10}}>Variables</Typography>
|
||||
<List>
|
||||
{requiredVariables.map((data, index) => {
|
||||
return <VariableSection key={index} variable={data} />;
|
||||
return (
|
||||
<VariableSection key={index} variable={data} />
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</span>
|
||||
) : null}
|
||||
: null}
|
||||
|
||||
{requiredTriggers.length > 0 ? (
|
||||
|
||||
{requiredTriggers.length > 0 ?
|
||||
<span>
|
||||
<Typography variant="body1" style={{ marginTop: 10 }}>
|
||||
Triggers
|
||||
</Typography>
|
||||
<Typography variant="body1" style={{marginTop: 10}}>Triggers</Typography>
|
||||
<List>
|
||||
{requiredTriggers.map((data, index) => {
|
||||
return <TriggerSection key={index} trigger={data} />;
|
||||
return (
|
||||
<TriggerSection key={index} trigger={data} />
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</span>
|
||||
) : null}
|
||||
<div style={{ textAlign: "center", display: "flex", marginTop: 20 }}>
|
||||
<ButtonGroup style={{ margin: "auto" }}>
|
||||
: null }
|
||||
<div style={{textAlign: "center", display: "flex", marginTop: 20, }}>
|
||||
<ButtonGroup style={{margin: "auto",}}>
|
||||
{/*
|
||||
<Button color="primary" variant={"outlined"} style={{
|
||||
}} onClick={() => {
|
||||
@@ -607,25 +490,21 @@ const ConfigureWorkflow = (props) => {
|
||||
Skip
|
||||
</Button>
|
||||
*/}
|
||||
<Button
|
||||
color="primary"
|
||||
variant={"contained"}
|
||||
style={{}}
|
||||
onClick={() => {
|
||||
<Button color="primary" variant={"contained"} style={{
|
||||
}} onClick={() => {
|
||||
if (itemChanged) {
|
||||
saveWorkflow(workflow);
|
||||
window.location.reload();
|
||||
saveWorkflow(workflow)
|
||||
window.location.reload()
|
||||
} else {
|
||||
setConfigureWorkflowModalOpen(false);
|
||||
setConfigureWorkflowModalOpen(false)
|
||||
}
|
||||
}}
|
||||
>
|
||||
}}>
|
||||
Finish setup
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default ConfigureWorkflow;
|
||||
export default ConfigureWorkflow
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import React, { useRef, useState } from "react";
|
||||
import { useEffect } from "react";
|
||||
import BackupIcon from "@material-ui/icons/Backup";
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import BackupIcon from '@material-ui/icons/Backup';
|
||||
|
||||
const dragOverStyle = {
|
||||
backgroundColor: "rgba(0,0,0,0.8)",
|
||||
border: "5px dashed white",
|
||||
borderRadius: "8px",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
position: "absolute",
|
||||
overflow: "hidden",
|
||||
backgroundColor: 'rgba(0,0,0,0.8)',
|
||||
border: '5px dashed white',
|
||||
borderRadius: '8px',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
overflow: 'hidden',
|
||||
zIndex: 100,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
};
|
||||
|
||||
const Dropzone = ({ children, style, onDrop }) => {
|
||||
@@ -56,21 +56,21 @@ const Dropzone = ({ children, style, onDrop }) => {
|
||||
useEffect(() => {
|
||||
if (!dropzoneRef.current) return;
|
||||
|
||||
dropzoneRef.current.addEventListener("dragover", handleDragOver);
|
||||
dropzoneRef.current.addEventListener("dragenter", handleDragEnter);
|
||||
dropzoneRef.current.addEventListener("dragleave", handleDragLeave);
|
||||
dropzoneRef.current.addEventListener("drop", handleDrop);
|
||||
dropzoneRef.current.addEventListener('dragover', handleDragOver);
|
||||
dropzoneRef.current.addEventListener('dragenter', handleDragEnter);
|
||||
dropzoneRef.current.addEventListener('dragleave', handleDragLeave);
|
||||
dropzoneRef.current.addEventListener('drop', handleDrop);
|
||||
|
||||
return () => {
|
||||
dropzoneRef.current.removeEventListener("dragover", handleDragOver);
|
||||
dropzoneRef.current.removeEventListener("dragenter", handleDragEnter);
|
||||
dropzoneRef.current.removeEventListener("dragleave", handleDragLeave);
|
||||
dropzoneRef.current.removeEventListener("drop", handleDrop);
|
||||
dropzoneRef.current.removeEventListener('dragover', handleDragOver);
|
||||
dropzoneRef.current.removeEventListener('dragenter', handleDragEnter);
|
||||
dropzoneRef.current.removeEventListener('dragleave', handleDragLeave);
|
||||
dropzoneRef.current.removeEventListener('drop', handleDrop);
|
||||
};
|
||||
}, [dropzoneRef]);
|
||||
|
||||
return (
|
||||
<div ref={dropzoneRef} style={{ position: "relative", ...style }}>
|
||||
<div ref={dropzoneRef} style={{ position: 'relative', ...style }}>
|
||||
{dragging && (
|
||||
<div style={dragOverStyle}>
|
||||
<BackupIcon fontSize="large" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
//import List from '@material-ui/core/List';
|
||||
//import ListItem from '@material-ui/core/ListItem';
|
||||
@@ -9,22 +9,22 @@ const FooterStyle = {
|
||||
left: "0",
|
||||
bottom: "0",
|
||||
height: "130px",
|
||||
backgroundColor: "rgba(15, 14, 31, 1)",
|
||||
backgroundColor: 'rgba(15, 14, 31, 1)',
|
||||
};
|
||||
|
||||
const FooterInfo = {
|
||||
maxWidth: "1150px",
|
||||
minWidth: "768px",
|
||||
textAlign: "center",
|
||||
margin: "auto",
|
||||
maxWidth: '1150px',
|
||||
minWidth: '768px',
|
||||
textAlign: 'center',
|
||||
margin: 'auto',
|
||||
};
|
||||
|
||||
const hrefStyle = {
|
||||
color: "#bdbdbd",
|
||||
textDecoration: "none",
|
||||
};
|
||||
textDecoration: "none"
|
||||
}
|
||||
|
||||
const Footer = (props) => {
|
||||
const Footer = props => {
|
||||
return (
|
||||
<div style={FooterStyle}>
|
||||
<div style={FooterInfo}>
|
||||
@@ -34,15 +34,15 @@ const Footer = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
const Box = (props) => {
|
||||
return (
|
||||
<div style={{ display: "flex" }}>
|
||||
<div style={{ flex: "1" }}>
|
||||
const Box = props => {
|
||||
return(
|
||||
<div style={{display: "flex"}}>
|
||||
<div style={{flex: "1"}}>
|
||||
<a style={hrefStyle} href="/about">
|
||||
<h1>About</h1>
|
||||
</a>
|
||||
</div>
|
||||
<div style={{ flex: "1" }}>
|
||||
<div style={{flex: "1"}}>
|
||||
<a style={hrefStyle} href="/privacy-policy">
|
||||
<h1>Privacy Policy</h1>
|
||||
</a>
|
||||
|
||||
+236
-474
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,13 @@
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
import React, { useState } from "react";
|
||||
import React, {useState} from 'react';
|
||||
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
const LoginDialog = (props) => {
|
||||
const {
|
||||
classes,
|
||||
onClose,
|
||||
open,
|
||||
globalUrl,
|
||||
isLoggedIn,
|
||||
setIsLoggedIn,
|
||||
...other
|
||||
} = props;
|
||||
const LoginDialog = props => {
|
||||
const { classes, onClose, open, globalUrl, isLoggedIn, setIsLoggedIn, ...other } = props;
|
||||
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
@@ -28,91 +20,86 @@ const LoginDialog = (props) => {
|
||||
const [loginInfo, setLoginInfo] = useState("");
|
||||
|
||||
const handleValidateForm = () => {
|
||||
return username.length > 1 && password.length > 8;
|
||||
};
|
||||
return (username.length > 1 && password.length > 8);
|
||||
}
|
||||
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
|
||||
// Just use this one?
|
||||
var data =
|
||||
'{"username": "' + username + '", "password": "' + password + '"}';
|
||||
var baseurl = globalUrl;
|
||||
var data = '{"username": "' + username + '", "password": "' + password + '"}';
|
||||
var baseurl = globalUrl
|
||||
if (loginCheck) {
|
||||
var url = baseurl + "/login";
|
||||
var url = baseurl+'/login';
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: data,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
console.log(responseJson);
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
console.log(responseJson)
|
||||
//console.log(e)
|
||||
if (responseJson["success"] === false) {
|
||||
setLoginInfo(responseJson["reason"]);
|
||||
setLoginInfo(responseJson["reason"])
|
||||
} else {
|
||||
setLoginInfo("Successful login :)");
|
||||
onClose();
|
||||
setIsLoggedIn(true);
|
||||
setLoginInfo("Successful login :)")
|
||||
onClose()
|
||||
setIsLoggedIn(true)
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setLoginInfo("Error in userdata");
|
||||
.catch(error => {
|
||||
setLoginInfo("Error in userdata")
|
||||
});
|
||||
} else {
|
||||
url = baseurl + "/register";
|
||||
url = baseurl+'/register';
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: data,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
if (responseJson["success"] === false) {
|
||||
setLoginInfo(responseJson["reason"]);
|
||||
setLoginInfo(responseJson["reason"])
|
||||
} else {
|
||||
setLoginInfo("Successful register :)");
|
||||
onClose();
|
||||
setIsLoggedIn(true);
|
||||
setLoginInfo("Successful register :)")
|
||||
onClose()
|
||||
setIsLoggedIn(true)
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setLoginInfo("Error in userdata");
|
||||
.catch(error => {
|
||||
setLoginInfo("Error in userdata")
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const onChangeUser = (e) => {
|
||||
setUsername(e.target.value);
|
||||
};
|
||||
setUsername(e.target.value)
|
||||
}
|
||||
|
||||
const onChangePass = (e) => {
|
||||
setPassword(e.target.value);
|
||||
};
|
||||
setPassword(e.target.value)
|
||||
}
|
||||
|
||||
const onClickRegister = () => {
|
||||
setLoginCheck(!loginCheck);
|
||||
};
|
||||
setLoginCheck(!loginCheck)
|
||||
}
|
||||
|
||||
//var loginChange = loginCheck ? (<div><p onClick={setLoginCheck(false)}>Want to register? Click here.</p></div>) : (<div><p onClick={setLoginCheck(true)}>Go back to login? Click here.</p></div>);
|
||||
var formtitle = loginCheck ? <div>Login</div> : <div>Register</div>;
|
||||
var formButton = loginCheck ? (
|
||||
<div>Click to Register</div>
|
||||
) : (
|
||||
<div>Click to Login</div>
|
||||
);
|
||||
var formtitle = loginCheck ? <div>Login</div> : <div>Register</div>
|
||||
var formButton = loginCheck ? <div>Click to Register</div> : <div>Click to Login</div>
|
||||
|
||||
return (
|
||||
<Dialog modal open={open} onClose={onClose} {...other}>
|
||||
<DialogTitle>{formtitle}</DialogTitle>
|
||||
<form onSubmit={onSubmit} style={{ margin: "15px 15px 15px 15px" }}>
|
||||
<form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px"}}>
|
||||
Username
|
||||
<div>
|
||||
<TextField
|
||||
@@ -135,42 +122,18 @@ const LoginDialog = (props) => {
|
||||
onChange={onChangePass}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: "flex", marginTop: "15px" }}>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
type="submit"
|
||||
style={{ flex: "1", marginRight: "5px" }}
|
||||
disabled={!handleValidateForm()}
|
||||
>
|
||||
SUBMIT
|
||||
</Button>
|
||||
<div style={{display: "flex", marginTop: "15px"}}>
|
||||
<Button color="secondary" variant="contained" type="submit" style={{flex: "1", marginRight: "5px"}} disabled={!handleValidateForm()}>SUBMIT</Button>
|
||||
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
type="button"
|
||||
style={{ flex: "1" }}
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button color="primary" variant="contained" type="button" style={{flex: "1"}} onClick={onClose}>Cancel</Button>
|
||||
</div>
|
||||
{loginInfo}
|
||||
</form>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
onClick={onClickRegister}
|
||||
type="button"
|
||||
style={{ flex: "1" }}
|
||||
>
|
||||
{formButton}
|
||||
</Button>
|
||||
<div style={{display: "flex"}}>
|
||||
<Button color="secondary" variant="contained" onClick={onClickRegister} type="button" style={{flex: "1"}}>{formButton}</Button>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default LoginDialog;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { useState, useRef, useImperativeHandle } from "react";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import Menu, { MenuProps } from "@material-ui/core/Menu";
|
||||
import MenuItem, { MenuItemProps } from "@material-ui/core/MenuItem";
|
||||
import ArrowRight from "@material-ui/icons/ArrowRight";
|
||||
import clsx from "clsx";
|
||||
import React, {useState, useRef, useImperativeHandle} from 'react'
|
||||
import {makeStyles} from '@material-ui/core/styles'
|
||||
import Menu, {MenuProps} from '@material-ui/core/Menu'
|
||||
import MenuItem, {MenuItemProps} from '@material-ui/core/MenuItem'
|
||||
import ArrowRight from '@material-ui/icons/ArrowRight'
|
||||
import clsx from 'clsx'
|
||||
|
||||
//<MenuItemProps, 'button'>
|
||||
|
||||
@@ -42,12 +42,12 @@ import clsx from "clsx";
|
||||
// button: true;
|
||||
//}
|
||||
|
||||
const TRANSPARENT = "rgba(0,0,0,0)";
|
||||
const TRANSPARENT = 'rgba(0,0,0,0)'
|
||||
const useMenuItemStyles = makeStyles((theme) => ({
|
||||
root: (props: any) => ({
|
||||
backgroundColor: props.open ? theme.palette.action.hover : TRANSPARENT,
|
||||
}),
|
||||
}));
|
||||
backgroundColor: props.open ? theme.palette.action.hover : TRANSPARENT
|
||||
})
|
||||
}))
|
||||
|
||||
/**
|
||||
* Use as a drop-in replacement for `<MenuItem>` when you need to add cascading
|
||||
@@ -55,11 +55,11 @@ const useMenuItemStyles = makeStyles((theme) => ({
|
||||
*/
|
||||
//const NestedMenuItem = React.forwardRef<NestedMenuItemProps>(
|
||||
const NestedMenuItem = (props, ref) => {
|
||||
console.log(props, ref);
|
||||
console.log(props, ref)
|
||||
//function NestedMenuItem(props, ref) {
|
||||
const {
|
||||
parentMenuOpen,
|
||||
component = "div",
|
||||
component = 'div',
|
||||
label,
|
||||
rightIcon = <ArrowRight />,
|
||||
children,
|
||||
@@ -68,100 +68,94 @@ const NestedMenuItem = (props, ref) => {
|
||||
MenuProps = {},
|
||||
ContainerProps: ContainerPropsProp = {},
|
||||
...MenuItemProps
|
||||
} = props;
|
||||
} = props
|
||||
|
||||
const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);
|
||||
const [isSubMenuOpen, setIsSubMenuOpen] = useState(false)
|
||||
|
||||
const { ref: containerRefProp, ...ContainerProps } = ContainerPropsProp;
|
||||
const {ref: containerRefProp, ...ContainerProps} = ContainerPropsProp
|
||||
|
||||
const menuItemRef = useRef < HTMLLIElement > null;
|
||||
useImperativeHandle(ref, () => menuItemRef.current);
|
||||
const containerRef = useRef < HTMLDivElement > null;
|
||||
useImperativeHandle(containerRefProp, () => containerRef.current);
|
||||
const menuContainerRef = useRef < HTMLDivElement > null;
|
||||
|
||||
console.log(
|
||||
"PAST THIS: ",
|
||||
containerRefProp,
|
||||
menuItemRef,
|
||||
containerRef,
|
||||
menuContainerRef,
|
||||
ContainerProps
|
||||
);
|
||||
const menuItemRef = useRef<HTMLLIElement>(null)
|
||||
useImperativeHandle(ref, () => menuItemRef.current)
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
useImperativeHandle(containerRefProp, () => containerRef.current)
|
||||
const menuContainerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
console.log("PAST THIS: ", containerRefProp, menuItemRef, containerRef, menuContainerRef, ContainerProps)
|
||||
|
||||
const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setIsSubMenuOpen(true);
|
||||
setIsSubMenuOpen(true)
|
||||
|
||||
if (ContainerProps?.onMouseEnter) {
|
||||
ContainerProps.onMouseEnter(event);
|
||||
ContainerProps.onMouseEnter(event)
|
||||
}
|
||||
}
|
||||
};
|
||||
const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setIsSubMenuOpen(false);
|
||||
setIsSubMenuOpen(false)
|
||||
|
||||
if (ContainerProps?.onMouseLeave) {
|
||||
ContainerProps.onMouseLeave(event);
|
||||
ContainerProps.onMouseLeave(event)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Check if any immediate children are active
|
||||
const isSubmenuFocused = () => {
|
||||
const active = containerRef.current?.ownerDocument?.activeElement;
|
||||
const active = containerRef.current?.ownerDocument?.activeElement
|
||||
for (const child of menuContainerRef.current?.children ?? []) {
|
||||
if (child === active) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
return false
|
||||
}
|
||||
|
||||
const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
|
||||
if (event.target === containerRef.current) {
|
||||
setIsSubMenuOpen(true);
|
||||
setIsSubMenuOpen(true)
|
||||
}
|
||||
|
||||
if (ContainerProps?.onFocus) {
|
||||
ContainerProps.onFocus(event);
|
||||
ContainerProps.onFocus(event)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (event.key === "Escape") {
|
||||
return;
|
||||
if (event.key === 'Escape') {
|
||||
return
|
||||
}
|
||||
|
||||
if (isSubmenuFocused()) {
|
||||
event.stopPropagation();
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
const active = containerRef.current?.ownerDocument?.activeElement;
|
||||
const active = containerRef.current?.ownerDocument?.activeElement
|
||||
|
||||
if (event.key === "ArrowLeft" && isSubmenuFocused()) {
|
||||
containerRef.current?.focus();
|
||||
if (event.key === 'ArrowLeft' && isSubmenuFocused()) {
|
||||
containerRef.current?.focus()
|
||||
}
|
||||
|
||||
if (
|
||||
event.key === "ArrowRight" &&
|
||||
event.key === 'ArrowRight' &&
|
||||
event.target === containerRef.current &&
|
||||
event.target === active
|
||||
) {
|
||||
console.log("MENU: ", menuContainerRef);
|
||||
const firstChild = menuContainerRef.current.children[0];
|
||||
console.log("FIRST: ", firstChild);
|
||||
firstChild.focus();
|
||||
console.log("MENU: ", menuContainerRef)
|
||||
const firstChild = menuContainerRef.current.children[0]
|
||||
console.log("FIRST: ", firstChild)
|
||||
firstChild.focus()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const open = isSubMenuOpen && parentMenuOpen;
|
||||
const menuItemClasses = useMenuItemStyles({ open });
|
||||
const open = isSubMenuOpen && parentMenuOpen
|
||||
const menuItemClasses = useMenuItemStyles({open})
|
||||
|
||||
// Root element must have a `tabIndex` attribute for keyboard navigation
|
||||
let tabIndex;
|
||||
let tabIndex
|
||||
if (!props.disabled) {
|
||||
tabIndex = tabIndexProp !== undefined ? tabIndexProp : -1;
|
||||
tabIndex = tabIndexProp !== undefined ? tabIndexProp : -1
|
||||
}
|
||||
|
||||
console.log("PAST 2! ", tabIndex);
|
||||
console.log("PAST 2! ", tabIndex)
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -184,30 +178,30 @@ const NestedMenuItem = (props, ref) => {
|
||||
<Menu
|
||||
// Set pointer events to 'none' to prevent the invisible Popover div
|
||||
// from capturing events for clicks and hovers
|
||||
style={{ pointerEvents: "none" }}
|
||||
style={{pointerEvents: 'none'}}
|
||||
anchorEl={menuItemRef.current}
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
vertical: 'top',
|
||||
horizontal: 'right'
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
vertical: 'top',
|
||||
horizontal: 'left'
|
||||
}}
|
||||
open={open}
|
||||
autoFocus={false}
|
||||
disableAutoFocus
|
||||
disableEnforceFocus
|
||||
onClose={() => {
|
||||
setIsSubMenuOpen(false);
|
||||
setIsSubMenuOpen(false)
|
||||
}}
|
||||
>
|
||||
<div ref={menuContainerRef} style={{ pointerEvents: "auto" }}>
|
||||
<div ref={menuContainerRef} style={{pointerEvents: 'auto'}}>
|
||||
{children}
|
||||
</div>
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default NestedMenuItem;
|
||||
export default NestedMenuItem
|
||||
|
||||
@@ -1,45 +1,12 @@
|
||||
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
|
||||
import { useTheme } from "@material-ui/core/styles";
|
||||
import React, {useRef, useState, useEffect, useLayoutEffect} from 'react';
|
||||
import { useTheme } from '@material-ui/core/styles';
|
||||
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import {
|
||||
ListItemText,
|
||||
TextField,
|
||||
Drawer,
|
||||
Button,
|
||||
Paper,
|
||||
Grid,
|
||||
Tabs,
|
||||
InputAdornment,
|
||||
Tab,
|
||||
ButtonBase,
|
||||
Tooltip,
|
||||
Select,
|
||||
MenuItem,
|
||||
Divider,
|
||||
Dialog,
|
||||
Modal,
|
||||
DialogActions,
|
||||
DialogTitle,
|
||||
InputLabel,
|
||||
DialogContent,
|
||||
FormControl,
|
||||
IconButton,
|
||||
Menu,
|
||||
Input,
|
||||
FormGroup,
|
||||
FormControlLabel,
|
||||
Typography,
|
||||
Checkbox,
|
||||
Breadcrumbs,
|
||||
CircularProgress,
|
||||
Switch,
|
||||
Fade,
|
||||
} from "@material-ui/core";
|
||||
import { LockOpen as LockOpenIcon } from "@material-ui/icons";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { ListItemText, TextField, Drawer, Button, Paper, Grid, Tabs, InputAdornment, Tab, ButtonBase, Tooltip, Select, MenuItem, Divider, Dialog, Modal, DialogActions, DialogTitle, InputLabel, DialogContent, FormControl, IconButton, Menu, Input, FormGroup, FormControlLabel, Typography, Checkbox, Breadcrumbs, CircularProgress, Switch, Fade } from '@material-ui/core';
|
||||
import { LockOpen as LockOpenIcon } from '@material-ui/icons';
|
||||
|
||||
const ITEM_HEIGHT = 55;
|
||||
const ITEM_PADDING_TOP = 8;
|
||||
const ITEM_HEIGHT = 55
|
||||
const ITEM_PADDING_TOP = 8
|
||||
const MenuProps = {
|
||||
PaperProps: {
|
||||
style: {
|
||||
@@ -49,95 +16,64 @@ const MenuProps = {
|
||||
scrollX: "auto",
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const AuthenticationOauth2 = (props) => {
|
||||
const {
|
||||
saveWorkflow,
|
||||
selectedApp,
|
||||
workflow,
|
||||
selectedAction,
|
||||
authenticationType,
|
||||
getAppAuthentication,
|
||||
appAuthentication,
|
||||
setSelectedAction,
|
||||
setNewAppAuth,
|
||||
setAuthenticationModalOpen,
|
||||
} = props;
|
||||
const { saveWorkflow, selectedApp, workflow, selectedAction, authenticationType, getAppAuthentication, appAuthentication, setSelectedAction, setNewAppAuth, setAuthenticationModalOpen} = props;
|
||||
const theme = useTheme();
|
||||
|
||||
//const [update, setUpdate] = React.useState("|")
|
||||
const [defaultConfigSet, setDefaultConfigSet] = React.useState(
|
||||
authenticationType.client_id !== undefined &&
|
||||
authenticationType.client_id !== null &&
|
||||
authenticationType.client_id.length > 0 &&
|
||||
authenticationType.client_secret !== undefined &&
|
||||
authenticationType.client_secret !== null &&
|
||||
authenticationType.client_secret.length > 0
|
||||
);
|
||||
const [clientId, setClientId] = React.useState(
|
||||
defaultConfigSet ? authenticationType.client_id : ""
|
||||
);
|
||||
const [clientSecret, setClientSecret] = React.useState(
|
||||
defaultConfigSet ? authenticationType.client_secret : ""
|
||||
);
|
||||
const [oauthUrl, setOauthUrl] = React.useState("");
|
||||
const [buttonClicked, setButtonClicked] = React.useState(false);
|
||||
const [selectedScopes, setSelectedScopes] = React.useState([]);
|
||||
const allscopes =
|
||||
authenticationType.scope !== undefined ? authenticationType.scope : [];
|
||||
const [defaultConfigSet, setDefaultConfigSet] = React.useState(authenticationType.client_id !== undefined && authenticationType.client_id !== null && authenticationType.client_id.length > 0 && authenticationType.client_secret !== undefined && authenticationType.client_secret !== null && authenticationType.client_secret.length > 0)
|
||||
const [clientId, setClientId] = React.useState(defaultConfigSet ? authenticationType.client_id : "")
|
||||
const [clientSecret, setClientSecret] = React.useState(defaultConfigSet ? authenticationType.client_secret : "")
|
||||
const [oauthUrl, setOauthUrl] = React.useState("")
|
||||
const [buttonClicked, setButtonClicked] = React.useState(false)
|
||||
const [selectedScopes, setSelectedScopes] = React.useState([])
|
||||
const allscopes = authenticationType.scope !== undefined ? authenticationType.scope: []
|
||||
|
||||
const [manuallyConfigure, setManuallyConfigure] = React.useState(
|
||||
defaultConfigSet ? false : true
|
||||
);
|
||||
const [manuallyConfigure, setManuallyConfigure] = React.useState(defaultConfigSet ? false : true)
|
||||
const [authenticationOption, setAuthenticationOptions] = React.useState({
|
||||
app: JSON.parse(JSON.stringify(selectedApp)),
|
||||
fields: {},
|
||||
label: "",
|
||||
usage: [
|
||||
{
|
||||
usage: [{
|
||||
workflow_id: workflow.id,
|
||||
},
|
||||
],
|
||||
}],
|
||||
id: uuidv4(),
|
||||
active: true,
|
||||
});
|
||||
})
|
||||
|
||||
if (selectedApp.authentication === undefined) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
const handleOauth2Request = (client_id, client_secret, oauth_url, scopes) => {
|
||||
setButtonClicked(true);
|
||||
console.log("SCOPES: ", scopes);
|
||||
setButtonClicked(true)
|
||||
console.log("SCOPES: ", scopes)
|
||||
|
||||
var resources = "";
|
||||
if (scopes !== undefined && (scopes !== null) & (scopes.length > 0)) {
|
||||
var resources = ""
|
||||
if (scopes !== undefined && scopes !== null & scopes.length > 0) {
|
||||
//scopes.push("offline_access")
|
||||
resources = scopes.join(",");
|
||||
resources = scopes.join(",")
|
||||
}
|
||||
|
||||
const authentication_url = authenticationType.token_uri;
|
||||
const authentication_url = authenticationType.token_uri
|
||||
//console.log("AUTH: ", authenticationType)
|
||||
//console.log("SCOPES2: ", resources)
|
||||
const redirectUri = `${window.location.protocol}//${window.location.host}/set_authentication`;
|
||||
var state = `workflow_id%3D${workflow.id}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`;
|
||||
const redirectUri = `${window.location.protocol}//${window.location.host}/set_authentication`
|
||||
var state = `workflow_id%3D${workflow.id}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`
|
||||
if (oauth_url !== undefined && oauth_url !== null && oauth_url.length > 0) {
|
||||
state += `%26oauth_url%3d${oauth_url}`;
|
||||
console.log("ADDING OAUTH2 URL: ", state);
|
||||
state += `%26oauth_url%3d${oauth_url}`
|
||||
console.log("ADDING OAUTH2 URL: ", state)
|
||||
}
|
||||
|
||||
if (
|
||||
authenticationType.refresh_uri !== undefined &&
|
||||
authenticationType.refresh_uri !== null &&
|
||||
authenticationType.refresh_uri.length > 0
|
||||
) {
|
||||
state += `%26refresh_uri%3d${authenticationType.refresh_uri}`;
|
||||
if (authenticationType.refresh_uri !== undefined && authenticationType.refresh_uri !== null && authenticationType.refresh_uri.length > 0) {
|
||||
state += `%26refresh_uri%3d${authenticationType.refresh_uri}`
|
||||
} else {
|
||||
state += `%26refresh_uri%3d${authentication_url}`;
|
||||
state += `%26refresh_uri%3d${authentication_url}`
|
||||
}
|
||||
|
||||
const url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${resources}&prompt=consent&state=${state}&access_type=offline`;
|
||||
const url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${resources}&prompt=consent&state=${state}&access_type=offline`
|
||||
|
||||
//const url = `https://accounts.zoho.com/oauth/v2/auth?response_type=code&client_id=${client_id}&scope=AaaServer.profile.Read&redirect_uri=${redirectUri}&prompt=consent`
|
||||
//console.log("Full URI: ", url)
|
||||
@@ -148,17 +84,18 @@ const AuthenticationOauth2 = (props) => {
|
||||
// How can we get a callback properly realtime?
|
||||
// How can we properly try-catch without breaks on error?
|
||||
try {
|
||||
var newwin = window.open(url, "", "width=800,height=600");
|
||||
|
||||
var newwin = window.open(url, "", "width=800,height=600")
|
||||
//console.log(newwin)
|
||||
|
||||
var open = true;
|
||||
var open = true
|
||||
const timer = setInterval(() => {
|
||||
if (newwin.closed) {
|
||||
setButtonClicked(false);
|
||||
setButtonClicked(false)
|
||||
clearInterval(timer);
|
||||
//alert('"Secure Payment" window closed!');
|
||||
|
||||
getAppAuthentication(true, true);
|
||||
getAppAuthentication(true, true)
|
||||
}
|
||||
}, 1000);
|
||||
//do {
|
||||
@@ -173,35 +110,28 @@ const AuthenticationOauth2 = (props) => {
|
||||
//}
|
||||
//while(open === true)
|
||||
} catch (e) {
|
||||
alert.error(
|
||||
"Failed authentication - probably bad credentials. Try again"
|
||||
);
|
||||
setButtonClicked(false);
|
||||
alert.error("Failed authentication - probably bad credentials. Try again")
|
||||
setButtonClicked(false)
|
||||
}
|
||||
|
||||
return;
|
||||
return
|
||||
//do {
|
||||
//} while (
|
||||
};
|
||||
}
|
||||
|
||||
authenticationOption.app.actions = [];
|
||||
|
||||
authenticationOption.app.actions = []
|
||||
|
||||
for (var key in selectedApp.authentication.parameters) {
|
||||
if (
|
||||
authenticationOption.fields[
|
||||
selectedApp.authentication.parameters[key].name
|
||||
] === undefined
|
||||
) {
|
||||
authenticationOption.fields[
|
||||
selectedApp.authentication.parameters[key].name
|
||||
] = "";
|
||||
if (authenticationOption.fields[selectedApp.authentication.parameters[key].name] === undefined) {
|
||||
authenticationOption.fields[selectedApp.authentication.parameters[key].name] = ""
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmitCheck = () => {
|
||||
console.log("NEW AUTH: ", authenticationOption);
|
||||
console.log("NEW AUTH: ", authenticationOption)
|
||||
if (authenticationOption.label.length === 0) {
|
||||
authenticationOption.label = `Auth for ${selectedApp.name}`;
|
||||
authenticationOption.label = `Auth for ${selectedApp.name}`
|
||||
//alert.info("Label can't be empty")
|
||||
//return
|
||||
}
|
||||
@@ -209,65 +139,44 @@ const AuthenticationOauth2 = (props) => {
|
||||
// Automatically mapping fields that already exist (predefined).
|
||||
// Warning if fields are NOT filled
|
||||
for (var key in selectedApp.authentication.parameters) {
|
||||
if (
|
||||
authenticationOption.fields[
|
||||
selectedApp.authentication.parameters[key].name
|
||||
].length === 0
|
||||
) {
|
||||
if (
|
||||
selectedApp.authentication.parameters[key].value !== undefined &&
|
||||
selectedApp.authentication.parameters[key].value !== null &&
|
||||
selectedApp.authentication.parameters[key].value.length > 0
|
||||
) {
|
||||
authenticationOption.fields[
|
||||
selectedApp.authentication.parameters[key].name
|
||||
] = selectedApp.authentication.parameters[key].value;
|
||||
if (authenticationOption.fields[selectedApp.authentication.parameters[key].name].length === 0) {
|
||||
if (selectedApp.authentication.parameters[key].value !== undefined && selectedApp.authentication.parameters[key].value !== null && selectedApp.authentication.parameters[key].value.length > 0) {
|
||||
authenticationOption.fields[selectedApp.authentication.parameters[key].name] = selectedApp.authentication.parameters[key].value
|
||||
} else {
|
||||
if (
|
||||
selectedApp.authentication.parameters[key].schema.type === "bool"
|
||||
) {
|
||||
authenticationOption.fields[
|
||||
selectedApp.authentication.parameters[key].name
|
||||
] = "false";
|
||||
if (selectedApp.authentication.parameters[key].schema.type === "bool") {
|
||||
authenticationOption.fields[selectedApp.authentication.parameters[key].name] = "false"
|
||||
} else {
|
||||
alert.info(
|
||||
"Field " +
|
||||
selectedApp.authentication.parameters[key].name +
|
||||
" can't be empty"
|
||||
);
|
||||
return;
|
||||
alert.info("Field "+selectedApp.authentication.parameters[key].name+" can't be empty")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Action: ", selectedAction);
|
||||
selectedAction.authentication_id = authenticationOption.id;
|
||||
selectedAction.selectedAuthentication = authenticationOption;
|
||||
if (
|
||||
selectedAction.authentication === undefined ||
|
||||
selectedAction.authentication === null
|
||||
) {
|
||||
selectedAction.authentication = [authenticationOption];
|
||||
console.log("Action: ", selectedAction)
|
||||
selectedAction.authentication_id = authenticationOption.id
|
||||
selectedAction.selectedAuthentication = authenticationOption
|
||||
if (selectedAction.authentication === undefined || selectedAction.authentication === null) {
|
||||
selectedAction.authentication = [authenticationOption]
|
||||
} else {
|
||||
selectedAction.authentication.push(authenticationOption);
|
||||
selectedAction.authentication.push(authenticationOption)
|
||||
}
|
||||
|
||||
setSelectedAction(selectedAction);
|
||||
setSelectedAction(selectedAction)
|
||||
|
||||
var newAuthOption = JSON.parse(JSON.stringify(authenticationOption));
|
||||
var newFields = [];
|
||||
var newAuthOption = JSON.parse(JSON.stringify(authenticationOption))
|
||||
var newFields = []
|
||||
for (const key in newAuthOption.fields) {
|
||||
const value = newAuthOption.fields[key];
|
||||
const value = newAuthOption.fields[key]
|
||||
newFields.push({
|
||||
key: key,
|
||||
value: value,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
console.log("FIELDS: ", newFields);
|
||||
newAuthOption.fields = newFields;
|
||||
setNewAppAuth(newAuthOption);
|
||||
console.log("FIELDS: ", newFields)
|
||||
newAuthOption.fields = newFields
|
||||
setNewAppAuth(newAuthOption)
|
||||
//appAuthentication.push(newAuthOption)
|
||||
//setAppAuthentication(appAuthentication)
|
||||
//
|
||||
@@ -281,50 +190,33 @@ const AuthenticationOauth2 = (props) => {
|
||||
{selectedAction.authentication.map(data => (
|
||||
<MenuItem key={data.id} style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
||||
*/
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const handleScopeChange = (event) => {
|
||||
const {
|
||||
target: { value },
|
||||
} = event;
|
||||
|
||||
console.log("VALUE: ", value);
|
||||
console.log("VALUE: ", value)
|
||||
|
||||
// On autofill we get a the stringified value.
|
||||
setSelectedScopes(typeof value === "string" ? value.split(",") : value);
|
||||
};
|
||||
setSelectedScopes(typeof value === 'string' ? value.split(',') : value)
|
||||
}
|
||||
|
||||
if (
|
||||
authenticationOption.label === null ||
|
||||
authenticationOption.label === undefined
|
||||
) {
|
||||
authenticationOption.label = selectedApp.name + " authentication";
|
||||
|
||||
if (authenticationOption.label === null || authenticationOption.label === undefined) {
|
||||
authenticationOption.label = selectedApp.name+" authentication"
|
||||
}
|
||||
|
||||
//console.log(
|
||||
return (
|
||||
<div>
|
||||
<DialogTitle>
|
||||
<div style={{ color: "white" }}>
|
||||
Authentication for {selectedApp.name}
|
||||
</div>
|
||||
</DialogTitle>
|
||||
<DialogTitle><div style={{color: "white"}}>Authentication for {selectedApp.name}</div></DialogTitle>
|
||||
<DialogContent>
|
||||
<span style={{}}>
|
||||
<b>
|
||||
Oauth2 requires a client ID and secret to authenticate. This is
|
||||
usually made in the remote system.
|
||||
</b>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="norefferer"
|
||||
href="https://shuffler.io/docs/apps#authentication"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
>
|
||||
{" "}
|
||||
Learn more about Oauth2 with Shuffle
|
||||
</a>
|
||||
<div />
|
||||
<b>Oauth2 requires a client ID and secret to authenticate. This is usually made in the remote system.</b>
|
||||
<a target="_blank" rel="norefferer" href="https://shuffler.io/docs/apps#authentication" style={{textDecoration: "none", color: "#f85a3e"}}> Learn more about Oauth2 with Shuffle</a><div/>
|
||||
</span>
|
||||
{/*<TextField
|
||||
style={{backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}}
|
||||
@@ -348,77 +240,54 @@ const AuthenticationOauth2 = (props) => {
|
||||
<Divider style={{marginTop: 15, marginBottom: 15, backgroundColor: "rgb(91, 96, 100)"}}/>
|
||||
*/}
|
||||
|
||||
{!manuallyConfigure ? null : (
|
||||
{!manuallyConfigure ? null :
|
||||
<span>
|
||||
{selectedApp.authentication.parameters.map((data, index) => {
|
||||
//console.log(data, index)
|
||||
if (data.name === "client_id" || data.name === "client_secret") {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
if (data.name !== "url") {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
if (oauthUrl.length === 0) {
|
||||
setOauthUrl(data.value);
|
||||
setOauthUrl(data.value)
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={index} style={{ marginTop: 10 }}>
|
||||
<LockOpenIcon style={{ marginRight: 10 }} />
|
||||
<div key={index} style={{marginTop: 10}}>
|
||||
<LockOpenIcon style={{marginRight: 10}}/>
|
||||
<b>{data.name}</b>
|
||||
|
||||
{data.schema !== undefined &&
|
||||
data.schema !== null &&
|
||||
data.schema.type === "bool" ? (
|
||||
{data.schema !== undefined && data.schema !== null && data.schema.type === "bool" ?
|
||||
<Select
|
||||
SelectDisplayProps={{
|
||||
style: {
|
||||
marginLeft: 10,
|
||||
},
|
||||
}
|
||||
}}
|
||||
defaultValue={"false"}
|
||||
fullWidth
|
||||
onChange={(e) => {
|
||||
console.log("Value: ", e.target.value);
|
||||
authenticationOption.fields[data.name] = e.target.value;
|
||||
}}
|
||||
style={{
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
height: 50,
|
||||
console.log("Value: ", e.target.value)
|
||||
authenticationOption.fields[data.name] = e.target.value
|
||||
}}
|
||||
style={{backgroundColor: theme.palette.surfaceColor, color: "white", height: 50}}
|
||||
>
|
||||
<MenuItem
|
||||
key={"false"}
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
}}
|
||||
value={"false"}
|
||||
>
|
||||
<MenuItem key={"false"} style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={"false"}>
|
||||
false
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
key={"true"}
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
}}
|
||||
value={"true"}
|
||||
>
|
||||
<MenuItem key={"true"} style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={"true"}>
|
||||
true
|
||||
</MenuItem>
|
||||
</Select>
|
||||
) : (
|
||||
:
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
style={{backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}}
|
||||
InputProps={{
|
||||
style: {
|
||||
style:{
|
||||
color: "white",
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
@@ -427,45 +296,32 @@ const AuthenticationOauth2 = (props) => {
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
type={
|
||||
data.example !== undefined &&
|
||||
data.example.includes("***")
|
||||
? "password"
|
||||
: "text"
|
||||
}
|
||||
type={data.example !== undefined && data.example.includes("***") ? "password" : "text"}
|
||||
color="primary"
|
||||
defaultValue={
|
||||
data.value !== undefined && data.value !== null
|
||||
? data.value
|
||||
: ""
|
||||
}
|
||||
defaultValue={data.value !== undefined && data.value !== null ? data.value : ""}
|
||||
placeholder={data.example}
|
||||
onChange={(event) => {
|
||||
authenticationOption.fields[data.name] =
|
||||
event.target.value;
|
||||
console.log("Setting oauth url");
|
||||
setOauthUrl(event.target.value);
|
||||
authenticationOption.fields[data.name] = event.target.value
|
||||
console.log("Setting oauth url")
|
||||
setOauthUrl(event.target.value)
|
||||
//const [oauthUrl, setOauthUrl] = React.useState("")
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
})}
|
||||
{allscopes.length === 0 ? null : (
|
||||
{allscopes.length === 0 ? null :
|
||||
<Select
|
||||
multiple
|
||||
value={selectedScopes}
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
}}
|
||||
style={{backgroundColor: theme.palette.inputColor, color: "white", }}
|
||||
onChange={(e) => {
|
||||
handleScopeChange(e);
|
||||
handleScopeChange(e)
|
||||
}}
|
||||
fullWidth
|
||||
input={<Input id="select-multiple-native" />}
|
||||
renderValue={(selected) => selected.join(", ")}
|
||||
renderValue={(selected) => selected.join(', ')}
|
||||
MenuProps={MenuProps}
|
||||
>
|
||||
{allscopes.map((data, index) => {
|
||||
@@ -474,18 +330,14 @@ const AuthenticationOauth2 = (props) => {
|
||||
<Checkbox checked={selectedScopes.indexOf(data) > -1} />
|
||||
<ListItemText primary={data} />
|
||||
</MenuItem>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
)}
|
||||
}
|
||||
<TextField
|
||||
style={{
|
||||
marginTop: 20,
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
style={{marginTop: 20, backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}}
|
||||
InputProps={{
|
||||
style: {
|
||||
style:{
|
||||
color: "white",
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
@@ -497,17 +349,14 @@ const AuthenticationOauth2 = (props) => {
|
||||
color="primary"
|
||||
placeholder={"Client ID"}
|
||||
onChange={(event) => {
|
||||
setClientId(event.target.value);
|
||||
setClientId(event.target.value)
|
||||
//authenticationOption.label = event.target.value
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
style={{backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}}
|
||||
InputProps={{
|
||||
style: {
|
||||
style:{
|
||||
color: "white",
|
||||
marginLeft: "5px",
|
||||
maxWidth: "95%",
|
||||
@@ -519,72 +368,58 @@ const AuthenticationOauth2 = (props) => {
|
||||
color="primary"
|
||||
placeholder={"Client Secret"}
|
||||
onChange={(event) => {
|
||||
setClientSecret(event.target.value);
|
||||
setClientSecret(event.target.value)
|
||||
//authenticationOption.label = event.target.value
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
<Button
|
||||
style={{
|
||||
marginBottom: 40,
|
||||
marginTop: 20,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
disabled={
|
||||
clientSecret.length === 0 || clientId.length === 0 || buttonClicked
|
||||
}
|
||||
<Button
|
||||
style={{marginBottom: 40, marginTop: 20, borderRadius: theme.palette.borderRadius}}
|
||||
disabled={clientSecret.length === 0 || clientId.length === 0 || buttonClicked}
|
||||
variant="contained"
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
handleOauth2Request(
|
||||
clientId,
|
||||
clientSecret,
|
||||
oauthUrl,
|
||||
selectedScopes
|
||||
);
|
||||
handleOauth2Request(clientId, clientSecret, oauthUrl, selectedScopes)
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
{buttonClicked ? (
|
||||
<CircularProgress style={{ color: "white" }} />
|
||||
) : (
|
||||
{buttonClicked ?
|
||||
<CircularProgress style={{color: "white", }} />
|
||||
:
|
||||
"Oauth2 request"
|
||||
)}
|
||||
}
|
||||
</Button>
|
||||
|
||||
{defaultConfigSet ? (
|
||||
{defaultConfigSet ?
|
||||
<span style={{}}>
|
||||
... or
|
||||
<Button
|
||||
style={{
|
||||
marginLeft: 10,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
style={{marginLeft: 10, borderRadius: theme.palette.borderRadius}}
|
||||
disabled={clientSecret.length === 0 || clientId.length === 0}
|
||||
variant="text"
|
||||
onClick={() => {
|
||||
setManuallyConfigure(!manuallyConfigure);
|
||||
setManuallyConfigure(!manuallyConfigure)
|
||||
|
||||
if (manuallyConfigure) {
|
||||
setClientId(authenticationType.client_id);
|
||||
setClientSecret(authenticationType.client_secret);
|
||||
setClientId(authenticationType.client_id)
|
||||
setClientSecret(authenticationType.client_secret)
|
||||
} else {
|
||||
setClientId("");
|
||||
setClientSecret("");
|
||||
setClientId("")
|
||||
setClientSecret("")
|
||||
}
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
{manuallyConfigure
|
||||
? "Use auto-config"
|
||||
: "Manually configure Oauth2"}
|
||||
{manuallyConfigure ? "Use auto-config" : "Manually configure Oauth2"}
|
||||
</Button>
|
||||
</span>
|
||||
) : null}
|
||||
:
|
||||
null
|
||||
}
|
||||
</DialogContent>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default AuthenticationOauth2;
|
||||
export default AuthenticationOauth2
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,68 +1,65 @@
|
||||
import React, { useState, useEffect, useLayoutEffect } from "react";
|
||||
import * as cytoscape from "cytoscape";
|
||||
import CytoscapeComponent from "react-cytoscapejs";
|
||||
import cystyle from "../defaultCytoscapeStyle";
|
||||
import React, {useState, useEffect, useLayoutEffect} from 'react';
|
||||
import * as cytoscape from 'cytoscape';
|
||||
import CytoscapeComponent from 'react-cytoscapejs';
|
||||
import cystyle from '../defaultCytoscapeStyle';
|
||||
|
||||
const surfaceColor = "#27292D";
|
||||
const surfaceColor = "#27292D"
|
||||
const CytoscapeWrapper = (props) => {
|
||||
const { globalUrl, inworkflow } = props;
|
||||
|
||||
const [elements, setElements] = useState([]);
|
||||
const [workflow, setWorkflow] = useState(inworkflow);
|
||||
const [cy, setCy] = React.useState();
|
||||
const bodyWidth = 200;
|
||||
const bodyHeight = 150;
|
||||
const [elements, setElements] = useState([])
|
||||
const [workflow, setWorkflow] = useState(inworkflow)
|
||||
const [cy, setCy] = React.useState()
|
||||
const bodyWidth = 200
|
||||
const bodyHeight = 150
|
||||
|
||||
const setupGraph = () => {
|
||||
const actions = workflow.actions.map((action) => {
|
||||
const node = {};
|
||||
node.position = action.position;
|
||||
node.data = action;
|
||||
const actions = workflow.actions.map(action => {
|
||||
const node = {}
|
||||
node.position = action.position
|
||||
node.data = action
|
||||
|
||||
node.data._id = action["id"];
|
||||
node.data.type = "ACTION";
|
||||
node.isStartNode = action["id"] === workflow.start;
|
||||
node.data._id = action["id"]
|
||||
node.data.type = "ACTION"
|
||||
node.isStartNode = action["id"] === workflow.start
|
||||
|
||||
var example = "";
|
||||
if (
|
||||
action.example !== undefined &&
|
||||
action.example !== null &&
|
||||
action.example.length > 0
|
||||
) {
|
||||
example = action.example;
|
||||
|
||||
var example = ""
|
||||
if (action.example !== undefined && action.example !== null && action.example.length > 0) {
|
||||
example = action.example
|
||||
}
|
||||
|
||||
node.data.example = example;
|
||||
node.data.example = example
|
||||
return node;
|
||||
});
|
||||
})
|
||||
|
||||
const triggers = workflow.triggers.map((trigger) => {
|
||||
const node = {};
|
||||
node.position = trigger.position;
|
||||
node.data = trigger;
|
||||
const triggers = workflow.triggers.map(trigger => {
|
||||
const node = {}
|
||||
node.position = trigger.position
|
||||
node.data = trigger
|
||||
|
||||
node.data._id = trigger["id"];
|
||||
node.data.type = "TRIGGER";
|
||||
node.data._id = trigger["id"]
|
||||
node.data.type = "TRIGGER"
|
||||
|
||||
return node;
|
||||
});
|
||||
})
|
||||
|
||||
// FIXME - tmp branch update
|
||||
var insertedNodes = [].concat(actions, triggers);
|
||||
var insertedNodes = [].concat(actions, triggers)
|
||||
const edges = workflow.branches.map((branch, index) => {
|
||||
//workflow.branches[index].conditions = [{
|
||||
|
||||
const edge = {};
|
||||
var conditions = workflow.branches[index].conditions;
|
||||
const edge = { };
|
||||
var conditions = workflow.branches[index].conditions
|
||||
if (conditions === undefined || conditions === null) {
|
||||
conditions = [];
|
||||
conditions = []
|
||||
}
|
||||
|
||||
var label = "";
|
||||
var label = ""
|
||||
if (conditions.length === 1) {
|
||||
label = conditions.length + " condition";
|
||||
label = conditions.length+" condition"
|
||||
} else if (conditions.length > 1) {
|
||||
label = conditions.length + " conditions";
|
||||
label = conditions.length+" conditions"
|
||||
}
|
||||
|
||||
edge.data = {
|
||||
@@ -72,7 +69,7 @@ const CytoscapeWrapper = (props) => {
|
||||
target: branch.destination_id,
|
||||
label: label,
|
||||
conditions: conditions,
|
||||
hasErrors: branch.has_errors,
|
||||
hasErrors: branch.has_errors
|
||||
};
|
||||
|
||||
// This is an attempt at prettier edges. The numbers are weird to work with.
|
||||
@@ -100,46 +97,38 @@ const CytoscapeWrapper = (props) => {
|
||||
*/
|
||||
|
||||
return edge;
|
||||
});
|
||||
})
|
||||
|
||||
setWorkflow(workflow);
|
||||
setWorkflow(workflow)
|
||||
|
||||
// Verifies if a branch is valid and skips others
|
||||
var newedges = [];
|
||||
var newedges = []
|
||||
for (var key in edges) {
|
||||
var item = edges[key];
|
||||
var item = edges[key]
|
||||
|
||||
const sourcecheck = insertedNodes.find(
|
||||
(data) => data.data.id === item.data.source
|
||||
);
|
||||
const destcheck = insertedNodes.find(
|
||||
(data) => data.data.id === item.data.target
|
||||
);
|
||||
const sourcecheck = insertedNodes.find(data => data.data.id === item.data.source)
|
||||
const destcheck = insertedNodes.find(data => data.data.id === item.data.target)
|
||||
if (sourcecheck === undefined || destcheck === undefined) {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
newedges.push(item);
|
||||
newedges.push(item)
|
||||
}
|
||||
|
||||
insertedNodes = insertedNodes.concat(newedges);
|
||||
setElements(insertedNodes);
|
||||
};
|
||||
insertedNodes = insertedNodes.concat(newedges)
|
||||
setElements(insertedNodes)
|
||||
}
|
||||
|
||||
if (elements.length === 0) {
|
||||
setupGraph();
|
||||
setupGraph()
|
||||
}
|
||||
|
||||
return (
|
||||
<CytoscapeComponent
|
||||
elements={elements}
|
||||
minZoom={0.35}
|
||||
maxZoom={2.0}
|
||||
style={{
|
||||
width: bodyWidth - 15,
|
||||
height: bodyHeight - 5,
|
||||
backgroundColor: surfaceColor,
|
||||
}}
|
||||
maxZoom={2.00}
|
||||
style={{width: bodyWidth-15, height: bodyHeight-5, backgroundColor: surfaceColor}}
|
||||
stylesheet={cystyle}
|
||||
boxSelectionEnabled={true}
|
||||
autounselectify={false}
|
||||
@@ -148,10 +137,10 @@ const CytoscapeWrapper = (props) => {
|
||||
// FIXME: There's something specific loading when
|
||||
// you do the first hover of a node. Why is this different?
|
||||
//console.log("CY: ", incy)
|
||||
setCy(incy);
|
||||
setCy(incy)
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default CytoscapeWrapper;
|
||||
export default CytoscapeWrapper
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect } from "react";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import { useEffect } from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
function ScrollToTop({ getUserNotifications, setCurpath, history }) {
|
||||
function ScrollToTop({getUserNotifications, setCurpath, history }) {
|
||||
useEffect(() => {
|
||||
const unlisten = history.listen(() => {
|
||||
window.scroll({
|
||||
@@ -10,15 +10,15 @@ function ScrollToTop({ getUserNotifications, setCurpath, history }) {
|
||||
behavior: "smooth",
|
||||
});
|
||||
|
||||
setCurpath(window.location.pathname);
|
||||
getUserNotifications();
|
||||
setCurpath(window.location.pathname)
|
||||
getUserNotifications()
|
||||
});
|
||||
return () => {
|
||||
unlisten();
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
return (null);
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/36904185/react-router-scroll-to-top-on-every-transition
|
||||
|
||||
@@ -1,105 +1,84 @@
|
||||
import React, { useState } from "react";
|
||||
import React, {useState} from 'react';
|
||||
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Divider from "@material-ui/core/Divider";
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
|
||||
const SettingsDialog = (props) => {
|
||||
const {
|
||||
classes,
|
||||
onClose,
|
||||
settingsOpen,
|
||||
settingsData,
|
||||
globalUrl,
|
||||
isLoggedIn,
|
||||
setIsLoggedIn,
|
||||
...other
|
||||
} = props;
|
||||
|
||||
const SettingsDialog = props => {
|
||||
const { classes, onClose, settingsOpen, settingsData, globalUrl, isLoggedIn, setIsLoggedIn, ...other } = props;
|
||||
|
||||
const [password1, setPassword1] = useState("");
|
||||
const [password2, setPassword2] = useState("");
|
||||
const [password3, setPassword3] = useState("");
|
||||
|
||||
const handleValidateForm = () => {
|
||||
var passlength = 10;
|
||||
if (
|
||||
password1 === password2 &&
|
||||
password1.length >= passlength &&
|
||||
password3.length >= passlength
|
||||
) {
|
||||
return true;
|
||||
var passlength = 10
|
||||
if (password1 === password2 && password1.length >= passlength && password3.length >= passlength) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
return false
|
||||
}
|
||||
|
||||
const onChangePass1 = (e) => {
|
||||
setPassword1(e.target.value);
|
||||
};
|
||||
setPassword1(e.target.value)
|
||||
}
|
||||
|
||||
const onChangePass2 = (e) => {
|
||||
setPassword2(e.target.value);
|
||||
};
|
||||
setPassword2(e.target.value)
|
||||
}
|
||||
|
||||
const onChangePass3 = (e) => {
|
||||
setPassword3(e.target.value);
|
||||
};
|
||||
setPassword3(e.target.value)
|
||||
}
|
||||
|
||||
const onSubmitPassReset = () => {
|
||||
console.log("Should change password");
|
||||
console.log("Should change password")
|
||||
// Rofl, this can't possibly be typesafe
|
||||
var data =
|
||||
'{"password1": "' +
|
||||
password1 +
|
||||
'", "password2": "' +
|
||||
password2 +
|
||||
'", "password3": "' +
|
||||
password3 +
|
||||
'"}';
|
||||
var data = '{"password1": "'+password1+'", "password2": "'+password2+'", "password3": "'+password3+'"}'
|
||||
|
||||
fetch(globalUrl + "/passwordreset", {
|
||||
fetch(globalUrl+"/passwordreset", {
|
||||
body: data,
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
console.log(responseJson);
|
||||
console.log(responseJson)
|
||||
if (responseJson.status === true) {
|
||||
console.log("SUCCESS");
|
||||
console.log("SUCCESS")
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
//PaperProps={{style: {minWidth: "500px"}}
|
||||
return (
|
||||
return(
|
||||
<Dialog open={settingsOpen} onClose={() => onClose()} {...other}>
|
||||
<DialogTitle>Settings</DialogTitle>
|
||||
<Divider />
|
||||
<div style={{ marginLeft: "15px", marginRight: "15px" }}>
|
||||
<h3>Username</h3>
|
||||
<div style={{marginLeft: "15px", marginRight: "15px"}}>
|
||||
<h3>
|
||||
Username
|
||||
</h3>
|
||||
{settingsData.username}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
marginLeft: "15px",
|
||||
marginRight: "15px",
|
||||
marginBottom: "15px",
|
||||
}}
|
||||
>
|
||||
<h3>ApiKey</h3>
|
||||
<div style={{marginLeft: "15px", marginRight: "15px", marginBottom: "15px"}}>
|
||||
<h3>
|
||||
ApiKey
|
||||
</h3>
|
||||
<TextField
|
||||
id="outlined-read-only-input"
|
||||
defaultValue={settingsData.apikey}
|
||||
value={settingsData.apikey}
|
||||
style={{ width: 320 }}
|
||||
style={{width: 320}}
|
||||
InputProps={{
|
||||
readOnly: true,
|
||||
}}
|
||||
@@ -107,15 +86,17 @@ const SettingsDialog = (props) => {
|
||||
/>
|
||||
</div>
|
||||
<Divider />
|
||||
<form style={{ margin: "15px 15px 15px 15px" }}>
|
||||
<h3>Change password</h3>
|
||||
<form style={{margin: "15px 15px 15px 15px"}}>
|
||||
<h3>
|
||||
Change password
|
||||
</h3>
|
||||
<div>
|
||||
<TextField
|
||||
id="standard-password-input"
|
||||
label="Current password"
|
||||
type="password"
|
||||
name="password"
|
||||
style={{ width: 320 }}
|
||||
style={{width: 320}}
|
||||
placeholder="********************************"
|
||||
autoComplete="current-password"
|
||||
margin="normal"
|
||||
@@ -129,7 +110,7 @@ const SettingsDialog = (props) => {
|
||||
type="password"
|
||||
placeholder="********************************"
|
||||
name="password"
|
||||
style={{ width: 320 }}
|
||||
style={{width: 320}}
|
||||
autoComplete="current-password"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
@@ -142,36 +123,19 @@ const SettingsDialog = (props) => {
|
||||
type="password"
|
||||
name="password"
|
||||
placeholder="********************************"
|
||||
style={{ width: 320 }}
|
||||
style={{width: 320}}
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={onChangePass3}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: "flex", marginTop: "10px" }}>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
onClick={onSubmitPassReset}
|
||||
type="button"
|
||||
style={{ flex: "1", marginRight: "5px" }}
|
||||
disabled={!handleValidateForm()}
|
||||
>
|
||||
SUBMIT
|
||||
</Button>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
type="button"
|
||||
style={{ flex: "1" }}
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<div style={{display: "flex", marginTop: "10px"}}>
|
||||
<Button color="secondary" variant="contained" onClick={onSubmitPassReset} type="button" style={{flex: "1", marginRight: "5px"}} disabled={!handleValidateForm()}>SUBMIT</Button>
|
||||
<Button color="primary" variant="contained" type="button" style={{flex: "1"}} onClick={onClose}>Cancel</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default SettingsDialog;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createBrowserHistory } from "history";
|
||||
import { createBrowserHistory } from 'history';
|
||||
|
||||
var localExport;
|
||||
if (typeof window !== "undefined") {
|
||||
localExport = createBrowserHistory({ forceRefresh: true });
|
||||
var localExport
|
||||
if (typeof window !== 'undefined') {
|
||||
localExport = createBrowserHistory({forceRefresh: true});
|
||||
}
|
||||
|
||||
export default localExport;
|
||||
export default localExport
|
||||
|
||||
+14
-19
@@ -1,45 +1,40 @@
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: "Nunito Sans";
|
||||
font-family: 'Nunito Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("./font1.woff2") format("woff2");
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
|
||||
U+FE2E-FE2F;
|
||||
src: url('./font1.woff2') format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: "Nunito Sans";
|
||||
font-family: 'Nunito Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("./font2.woff2") format("woff2");
|
||||
src: url('./font2.woff2') format('woff2');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: "Nunito Sans";
|
||||
font-family: 'Nunito Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("./font3.woff2") format("woff2");
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
|
||||
U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
||||
src: url('./font3.woff2') format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: "Nunito Sans";
|
||||
font-family: 'Nunito Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("./font4.woff2") format("woff2");
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
|
||||
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
src: url('./font4.woff2') format('woff2');
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: "Nunito Sans";
|
||||
font-family: 'Nunito Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("./font5.woff2") format("woff2");
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
||||
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
|
||||
U+FEFF, U+FFFD;
|
||||
src: url('./font5.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@@ -1,36 +1,34 @@
|
||||
const data = [
|
||||
{
|
||||
selector: "node",
|
||||
const data = [{
|
||||
selector: 'node',
|
||||
css: {
|
||||
label: "data(label)",
|
||||
"text-valign": "center",
|
||||
"font-family":
|
||||
"Segoe UI, Tahoma, Geneva, Verdana, sans-serif, sans-serif",
|
||||
"font-weight": "lighter",
|
||||
"margin-right": "10px",
|
||||
"font-size": "18px",
|
||||
width: "80px",
|
||||
height: "80px",
|
||||
color: "white",
|
||||
padding: "10px",
|
||||
margin: "5px",
|
||||
"border-width": "1px",
|
||||
"text-margin-x": "10px",
|
||||
cursor: "pointer",
|
||||
'label': 'data(label)',
|
||||
'text-valign': 'center',
|
||||
'font-family': 'Segoe UI, Tahoma, Geneva, Verdana, sans-serif, sans-serif',
|
||||
'font-weight': 'lighter',
|
||||
'margin-right': '10px',
|
||||
'font-size': '18px',
|
||||
'width': '80px',
|
||||
'height': '80px',
|
||||
'color': 'white',
|
||||
'padding': '10px',
|
||||
'margin': '5px',
|
||||
'border-width': '1px',
|
||||
'text-margin-x': '10px',
|
||||
'cursor': 'pointer',
|
||||
"z-index": 5001,
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: "edge",
|
||||
selector: 'edge',
|
||||
css: {
|
||||
"target-arrow-shape": "triangle",
|
||||
"target-arrow-color": "grey",
|
||||
"curve-style": "unbundled-bezier",
|
||||
label: "data(label)",
|
||||
"text-margin-y": "-15px",
|
||||
width: "5px",
|
||||
color: "white",
|
||||
cursor: "pointer",
|
||||
'target-arrow-shape': 'triangle',
|
||||
'target-arrow-color': 'grey',
|
||||
'curve-style': 'unbundled-bezier',
|
||||
'label': 'data(label)',
|
||||
'text-margin-y': '-15px',
|
||||
'width': '5px',
|
||||
"color": "white",
|
||||
'cursor': 'pointer',
|
||||
"line-fill": "linear-gradient",
|
||||
"line-gradient-stop-positions": ["0.0", "100"],
|
||||
"line-gradient-stop-colors": ["grey", "grey"],
|
||||
@@ -40,352 +38,352 @@ const data = [
|
||||
{
|
||||
selector: `node[type="ACTION"]`,
|
||||
css: {
|
||||
shape: "roundrectangle",
|
||||
"background-color": "#213243",
|
||||
"border-color": "#81c784",
|
||||
"background-width": "100%",
|
||||
"background-height": "100%",
|
||||
"border-radius": "5px",
|
||||
"z-index": 5001,
|
||||
'shape': 'roundrectangle',
|
||||
'background-color': '#213243',
|
||||
'border-color': '#81c784',
|
||||
'background-width': '100%',
|
||||
'background-height': '100%',
|
||||
'border-radius': '5px',
|
||||
'z-index': 5001,
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[type="COMMENT"]`,
|
||||
css: {
|
||||
shape: "roundrectangle",
|
||||
"background-color": "data(backgroundcolor)",
|
||||
"border-color": "#ffffff",
|
||||
color: "data(color)",
|
||||
width: "data(width)",
|
||||
height: "data(height)",
|
||||
"border-radius": "5px",
|
||||
'shape': 'roundrectangle',
|
||||
'background-color': 'data(backgroundcolor)',
|
||||
'border-color': '#ffffff',
|
||||
'color': 'data(color)',
|
||||
'width': 'data(width)',
|
||||
'height': 'data(height)',
|
||||
'border-radius': '5px',
|
||||
"background-opacity": "0.5",
|
||||
padding: "0px",
|
||||
margin: "0px",
|
||||
"text-margin-x": "0px",
|
||||
"z-index": 4999,
|
||||
'padding': '0px',
|
||||
'margin': '0px',
|
||||
'text-margin-x': '0px',
|
||||
'z-index': 4999,
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[app_name="Shuffle Tools"]`,
|
||||
css: {
|
||||
width: "30px",
|
||||
height: "30px",
|
||||
"z-index": 5000,
|
||||
"font-size": "0px",
|
||||
"background-width": "75%",
|
||||
"background-height": "75%",
|
||||
"background-color": "data(iconBackground)",
|
||||
"background-fill": "data(fillstyle)",
|
||||
"background-gradient-direction": "to-right",
|
||||
"background-gradient-stop-colors": "data(fillGradient)",
|
||||
},
|
||||
'width': '30px',
|
||||
'height': '30px',
|
||||
'z-index': 5000,
|
||||
'font-size': '0px',
|
||||
'background-width': '75%',
|
||||
'background-height': '75%',
|
||||
'background-color': 'data(iconBackground)',
|
||||
'background-fill': 'data(fillstyle)',
|
||||
'background-gradient-direction': 'to-right',
|
||||
'background-gradient-stop-colors': 'data(fillGradient)',
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: `node[app_name="Testing"]`,
|
||||
css: {
|
||||
width: "30px",
|
||||
height: "30px",
|
||||
"z-index": 5000,
|
||||
"font-size": "0px",
|
||||
'width': '30px',
|
||||
'height': '30px',
|
||||
'z-index': 5000,
|
||||
'font-size': '0px',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[?small_image]`,
|
||||
css: {
|
||||
"background-image": "data(small_image)",
|
||||
"text-halign": "right",
|
||||
'background-image': 'data(small_image)',
|
||||
'text-halign': 'right',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[?large_image]`,
|
||||
css: {
|
||||
"background-image": "data(large_image)",
|
||||
"text-halign": "right",
|
||||
'background-image': 'data(large_image)',
|
||||
'text-halign': 'right',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[type="CONDITION"]`,
|
||||
css: {
|
||||
shape: "diamond",
|
||||
"border-color": "##FFEB3B",
|
||||
padding: "30px",
|
||||
'shape': 'diamond',
|
||||
'border-color': '##FFEB3B',
|
||||
'padding': '30px'
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[type="eventAction"]`,
|
||||
css: {
|
||||
"background-color": "#edbd21",
|
||||
'background-color': '#edbd21',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[type="TRIGGER"]`,
|
||||
css: {
|
||||
shape: "octagon",
|
||||
"border-radius": "5px",
|
||||
"border-color": "orange",
|
||||
"background-color": "#213243",
|
||||
"background-width": "100%",
|
||||
"background-height": "100%",
|
||||
'shape': 'octagon',
|
||||
'border-radius': '5px',
|
||||
'border-color': 'orange',
|
||||
'background-color': '#213243',
|
||||
'background-width': '100%',
|
||||
'background-height': '100%',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[status="running"]`,
|
||||
css: {
|
||||
"border-color": "#81c784",
|
||||
'border-color': '#81c784',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[status="stopped"]`,
|
||||
css: {
|
||||
"border-color": "orange",
|
||||
'border-color': 'orange',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: 'node[type="mq"]',
|
||||
css: {
|
||||
"background-color": "#edbd21",
|
||||
'background-color': '#edbd21',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "node[?isButton]",
|
||||
selector: 'node[?isButton]',
|
||||
css: {
|
||||
shape: "ellipse",
|
||||
width: "15px",
|
||||
height: "15px",
|
||||
"z-index": "5002",
|
||||
"font-size": "0px",
|
||||
border: "1px solid rgba(255,255,255,0.9)",
|
||||
"background-image": "data(icon)",
|
||||
"background-color": "data(iconBackground)",
|
||||
'shape': 'ellipse',
|
||||
'width': '15px',
|
||||
'height': '15px',
|
||||
'z-index': '5002',
|
||||
'font-size': '0px',
|
||||
'border': '1px solid rgba(255,255,255,0.9)',
|
||||
'background-image': 'data(icon)',
|
||||
'background-color': 'data(iconBackground)',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "node[?isDescriptor]",
|
||||
selector: 'node[?isDescriptor]',
|
||||
css: {
|
||||
shape: "ellipse",
|
||||
"border-color": "#80deea",
|
||||
width: "5px",
|
||||
height: "5px",
|
||||
"z-index": "5002",
|
||||
"font-size": "10px",
|
||||
"text-valign": "center",
|
||||
"text-halign": "center",
|
||||
border: "1px solid black",
|
||||
"margin-right": "0px",
|
||||
"text-margin-x": "0px",
|
||||
"background-color": "data(imageColor)",
|
||||
"background-image": "data(image)",
|
||||
'shape': 'ellipse',
|
||||
'border-color': '#80deea',
|
||||
'width': '5px',
|
||||
'height': '5px',
|
||||
'z-index': '5002',
|
||||
'font-size': '10px',
|
||||
'text-valign': 'center',
|
||||
'text-halign': 'center',
|
||||
'border': '1px solid black',
|
||||
'margin-right': '0px',
|
||||
'text-margin-x': '0px',
|
||||
'background-color': 'data(imageColor)',
|
||||
'background-image': 'data(image)',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "node[?isStartNode]",
|
||||
selector: 'node[?isStartNode]',
|
||||
css: {
|
||||
shape: "ellipse",
|
||||
"border-color": "#80deea",
|
||||
width: "80px",
|
||||
height: "80px",
|
||||
"font-size": "18px",
|
||||
"background-width": "100%",
|
||||
"background-height": "100%",
|
||||
'shape': 'ellipse',
|
||||
'border-color': '#80deea',
|
||||
'width': '80px',
|
||||
'height': '80px',
|
||||
'font-size': '18px',
|
||||
'background-width': '100%',
|
||||
'background-height': '100%',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "node[!is_valid]",
|
||||
css: {
|
||||
"border-color": "red",
|
||||
"border-width": "10px",
|
||||
'border-color': 'red',
|
||||
'border-width': '10px',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ":selected",
|
||||
selector: ':selected',
|
||||
css: {
|
||||
"background-color": "#77b0d0",
|
||||
"border-color": "#77b0d0",
|
||||
"border-width": "20px",
|
||||
'background-color': '#77b0d0',
|
||||
'border-color': '#77b0d0',
|
||||
'border-width': '20px',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".skipped-highlight",
|
||||
selector: '.skipped-highlight',
|
||||
css: {
|
||||
"background-color": "grey",
|
||||
"border-color": "grey",
|
||||
"border-width": "8px",
|
||||
"transition-property": "background-color",
|
||||
"transition-duration": "0.5s",
|
||||
'background-color': 'grey',
|
||||
'border-color': 'grey',
|
||||
'border-width': '8px',
|
||||
'transition-property': 'background-color',
|
||||
'transition-duration': '0.5s',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".success-highlight",
|
||||
selector: '.success-highlight',
|
||||
css: {
|
||||
"background-color": "#41dcab",
|
||||
"border-color": "#41dcab",
|
||||
"border-width": "5px",
|
||||
"transition-property": "background-color",
|
||||
"transition-duration": "0.5s",
|
||||
'background-color': '#41dcab',
|
||||
'border-color': '#41dcab',
|
||||
'border-width': '5px',
|
||||
'transition-property': 'background-color',
|
||||
'transition-duration': '0.5s',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".hover-highlight",
|
||||
selector: '.hover-highlight',
|
||||
css: {
|
||||
"background-color": "#5f9265",
|
||||
"border-color": "#5f9265",
|
||||
"border-width": "5px",
|
||||
"transition-property": "background-color",
|
||||
"transition-duration": "0.5s",
|
||||
'background-color': '#5f9265',
|
||||
'border-color': '#5f9265',
|
||||
'border-width': '5px',
|
||||
'transition-property': 'background-color',
|
||||
'transition-duration': '0.5s',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".failure-highlight",
|
||||
selector: '.failure-highlight',
|
||||
css: {
|
||||
"background-color": "#8e3530",
|
||||
"border-color": "#8e3530",
|
||||
"border-width": "5px",
|
||||
"transition-property": "background-color",
|
||||
"transition-duration": "0.5s",
|
||||
'background-color': '#8e3530',
|
||||
'border-color': '#8e3530',
|
||||
'border-width': '5px',
|
||||
'transition-property': 'background-color',
|
||||
'transition-duration': '0.5s',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".not-executing-highlight",
|
||||
selector: '.not-executing-highlight',
|
||||
css: {
|
||||
"background-color": "grey",
|
||||
"border-color": "grey",
|
||||
"border-width": "5px",
|
||||
"transition-property": "#ffef47",
|
||||
"transition-duration": "0.25s",
|
||||
'background-color': 'grey',
|
||||
'border-color': 'grey',
|
||||
'border-width': '5px',
|
||||
'transition-property': '#ffef47',
|
||||
'transition-duration': '0.25s',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".executing-highlight",
|
||||
selector: '.executing-highlight',
|
||||
css: {
|
||||
"background-color": "#ffef47",
|
||||
"border-color": "#ffef47",
|
||||
"border-width": "8px",
|
||||
"transition-property": "border-width",
|
||||
"transition-duration": "0.25s",
|
||||
'background-color': '#ffef47',
|
||||
'border-color': '#ffef47',
|
||||
'border-width': '8px',
|
||||
'transition-property': 'border-width',
|
||||
'transition-duration': '0.25s',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".awaiting-data-highlight",
|
||||
selector: '.awaiting-data-highlight',
|
||||
css: {
|
||||
"background-color": "#f4ad42",
|
||||
"border-color": "#f4ad42",
|
||||
"border-width": "5px",
|
||||
"transition-property": "border-color",
|
||||
"transition-duration": "0.5s",
|
||||
'background-color': '#f4ad42',
|
||||
'border-color': '#f4ad42',
|
||||
'border-width': '5px',
|
||||
'transition-property': 'border-color',
|
||||
'transition-duration': '0.5s',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".shuffle-hover-highlight",
|
||||
selector: '.shuffle-hover-highlight',
|
||||
css: {
|
||||
"background-color": "#f85a3e",
|
||||
"border-color": "#f85a3e",
|
||||
"border-width": "12px",
|
||||
"transition-property": "border-width",
|
||||
"transition-duration": "0.25s",
|
||||
label: "data(label)",
|
||||
"font-size": "18px",
|
||||
color: "white",
|
||||
'background-color': "#f85a3e",
|
||||
'border-color': '#f85a3e',
|
||||
'border-width': '12px',
|
||||
'transition-property': 'border-width',
|
||||
'transition-duration': '0.25s',
|
||||
'label': 'data(label)',
|
||||
'font-size': '18px',
|
||||
'color': 'white',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "$node > node",
|
||||
selector: '$node > node',
|
||||
css: {
|
||||
"padding-top": "10px",
|
||||
"padding-left": "10px",
|
||||
"padding-bottom": "10px",
|
||||
"padding-right": "10px",
|
||||
'padding-top': '10px',
|
||||
'padding-left': '10px',
|
||||
'padding-bottom': '10px',
|
||||
'padding-right': '10px',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "edge.executing-highlight",
|
||||
selector: 'edge.executing-highlight',
|
||||
css: {
|
||||
width: "5px",
|
||||
"target-arrow-color": "#ffef47",
|
||||
"line-color": "#ffef47",
|
||||
"transition-property": "line-color, width",
|
||||
"transition-duration": "0.25s",
|
||||
'width': '5px',
|
||||
'target-arrow-color': '#ffef47',
|
||||
'line-color': '#ffef47',
|
||||
'transition-property': 'line-color, width',
|
||||
'transition-duration': '0.25s',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `edge[?decorator]`,
|
||||
css: {
|
||||
width: "1px",
|
||||
"line-style": "dashed",
|
||||
'width': '1px',
|
||||
'line-style': 'dashed',
|
||||
"line-fill": "linear-gradient",
|
||||
"target-arrow-color": "#f34079",
|
||||
'target-arrow-color': '#f34079',
|
||||
"line-gradient-stop-positions": ["0.0", "100"],
|
||||
"line-gradient-stop-colors": ["#f86a3e", "#f34079"],
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "edge.success-highlight",
|
||||
selector: 'edge.success-highlight',
|
||||
css: {
|
||||
width: "5px",
|
||||
"target-arrow-color": "#41dcab",
|
||||
"line-color": "#41dcab",
|
||||
"transition-property": "line-color, width",
|
||||
"transition-duration": "0.5s",
|
||||
'width': '5px',
|
||||
'target-arrow-color': '#41dcab',
|
||||
'line-color': '#41dcab',
|
||||
'transition-property': 'line-color, width',
|
||||
'transition-duration': '0.5s',
|
||||
"line-fill": "linear-gradient",
|
||||
"line-gradient-stop-positions": ["0.0", "100"],
|
||||
"line-gradient-stop-colors": ["#41dcab", "#41dcab"],
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".eh-handle",
|
||||
selector: '.eh-handle',
|
||||
style: {
|
||||
"background-color": "#337ab7",
|
||||
width: "1px",
|
||||
height: "1px",
|
||||
shape: "circle",
|
||||
"border-width": "1px",
|
||||
"border-color": "black",
|
||||
},
|
||||
'background-color': '#337ab7',
|
||||
'width': '1px',
|
||||
'height': '1px',
|
||||
'shape': 'circle',
|
||||
'border-width': '1px',
|
||||
'border-color': 'black'
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: ".eh-source",
|
||||
selector: '.eh-source',
|
||||
style: {
|
||||
"border-width": "3",
|
||||
"border-color": "#337ab7",
|
||||
},
|
||||
'border-width': '3',
|
||||
'border-color': '#337ab7'
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: ".eh-target",
|
||||
selector: '.eh-target',
|
||||
style: {
|
||||
"border-width": "3",
|
||||
"border-color": "#337ab7",
|
||||
},
|
||||
'border-width': '3',
|
||||
'border-color': '#337ab7'
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: ".eh-preview, .eh-ghost-edge",
|
||||
selector: '.eh-preview, .eh-ghost-edge',
|
||||
style: {
|
||||
"background-color": "#337ab7",
|
||||
"line-color": "#337ab7",
|
||||
"target-arrow-color": "#337ab7",
|
||||
"source-arrow-color": "#337ab7",
|
||||
},
|
||||
'background-color': '#337ab7',
|
||||
'line-color': '#337ab7',
|
||||
'target-arrow-color': '#337ab7',
|
||||
'source-arrow-color': '#337ab7'
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: "edge:selected",
|
||||
selector: 'edge:selected',
|
||||
css: {
|
||||
"target-arrow-color": "#f85a3e",
|
||||
'target-arrow-color': '#f85a3e',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `edge[?source_workflow]`,
|
||||
css: {
|
||||
"background-opacity": "1",
|
||||
"font-size": "0px",
|
||||
'font-size': '0px',
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: `node[?source_workflow]`,
|
||||
css: {
|
||||
"background-opacity": "0",
|
||||
"font-size": "0px",
|
||||
'font-size': '0px',
|
||||
},
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
//{
|
||||
// selector: 'edge[?hasErrors]',
|
||||
@@ -399,4 +397,5 @@ const data = [
|
||||
// },
|
||||
//},
|
||||
|
||||
export default data;
|
||||
|
||||
export default data
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import url("./css/nunito.css");
|
||||
@import url('./css/nunito.css');
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import "./index.css";
|
||||
import App from "./App";
|
||||
import * as serviceWorker from "./serviceWorker";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
ReactDOM.render(
|
||||
<App />
|
||||
, document.getElementById('root'));
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
// This link also includes instructions on opting out of this behavior.
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === "localhost" ||
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === "[::1]" ||
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
@@ -19,7 +19,7 @@ const isLocalhost = Boolean(
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
@@ -29,7 +29,7 @@ export function register(config) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
@@ -40,8 +40,8 @@ export function register(config) {
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
"This web app is being served cache-first by a service " +
|
||||
"worker. To learn more, visit https://goo.gl/SC7cgQ"
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://goo.gl/SC7cgQ'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
@@ -55,17 +55,17 @@ export function register(config) {
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === "installed") {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the old content will have been purged and
|
||||
// the fresh content will have been added to the cache.
|
||||
// It's the perfect time to display a "New content is
|
||||
// available; please refresh." message in your web app.
|
||||
console.log("New content is available; please refresh.");
|
||||
console.log('New content is available; please refresh.');
|
||||
|
||||
// Execute callback
|
||||
if (config.onUpdate) {
|
||||
@@ -75,7 +75,7 @@ function registerValidSW(swUrl, config) {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log("Content is cached for offline use.");
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config.onSuccess) {
|
||||
@@ -86,22 +86,22 @@ function registerValidSW(swUrl, config) {
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error during service worker registration:", error);
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
if (
|
||||
response.status === 404 ||
|
||||
response.headers.get("content-type").indexOf("javascript") === -1
|
||||
response.headers.get('content-type').indexOf('javascript') === -1
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
@@ -113,14 +113,14 @@ function checkValidServiceWorker(swUrl, config) {
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
"No internet connection found. App is running in offline mode."
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister();
|
||||
});
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,74 +1,49 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
const hrefStyle = {
|
||||
color: "#f85a3e",
|
||||
textDecoration: "none",
|
||||
};
|
||||
textDecoration: "none"
|
||||
}
|
||||
|
||||
const About = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>About</h1>
|
||||
|
||||
<p>
|
||||
Endao was started as a project in late 2018 as a free service to analyze
|
||||
APK (and soon IPA) files for vulnerabilities. The project was started
|
||||
after I,
|
||||
<a href="https://twitter.com/frikkylikeme" style={hrefStyle}>
|
||||
@frikkylikeme
|
||||
</a>
|
||||
, found multiple vulnerabilities in IoT devices based purely on their
|
||||
apps. As I wanted to learn more about these kind of vulnerabilities, I
|
||||
looked for solutions that work for my purpose, but didn't find any good,
|
||||
free and easy to use service - hence this site was born.
|
||||
Endao was started as a project in late 2018 as a free service to analyze APK (and soon IPA) files for vulnerabilities. The project was started after I,
|
||||
<a href="https://twitter.com/frikkylikeme" style={hrefStyle}>@frikkylikeme</a>
|
||||
, found multiple vulnerabilities in IoT devices based purely on their apps. As I wanted to learn more about these kind of vulnerabilities, I looked for solutions that work for my purpose, but didn't find any good, free and easy to use service - hence this site was born.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
My personal goal has and will always be to make the internet safer. As
|
||||
the IoT sphere grows, I want to be able to add ways of finding possible
|
||||
vulnerabilities fast to this website. This will hopefully include
|
||||
blogposts when I get around to it, as well as actual implementations.
|
||||
The vulnerability discovery field is in no way new, but I'll try my best
|
||||
to add whatever I can to it. As a disclaimer, I'm an "Ops" person, and I
|
||||
had never done frontend before creating this site. This is as much of a
|
||||
learning project within web development as it is in vulnerability
|
||||
discovery.
|
||||
My personal goal has and will always be to make the internet safer. As the IoT sphere grows, I want to be able to add ways of finding possible vulnerabilities fast to this website. This will hopefully include blogposts when I get around to it, as well as actual implementations. The vulnerability discovery field is in no way new, but I'll try my best to add whatever I can to it. As a disclaimer, I'm an "Ops" person, and I had never done frontend before creating this site. This is as much of a learning project within web development as it is in vulnerability discovery.
|
||||
</p>
|
||||
|
||||
<p>This site currently uses the following projects</p>
|
||||
<p>
|
||||
This site currently uses the following projects
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a style={hrefStyle} href="https://superanalyzer.rocks">
|
||||
SUPER Android Analyzer
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a style={hrefStyle} href="https://github.com/linkedin/qark">
|
||||
Qark
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a style={hrefStyle} href="https://virustotal.com">
|
||||
Virustotal
|
||||
</a>{" "}
|
||||
for malware checks in known APKs
|
||||
</li>
|
||||
<li><a style={hrefStyle} href="https://superanalyzer.rocks">SUPER Android Analyzer</a></li>
|
||||
<li><a style={hrefStyle} href="https://github.com/linkedin/qark">Qark</a></li>
|
||||
<li><a style={hrefStyle} href="https://virustotal.com">Virustotal</a> for malware checks in known APKs</li>
|
||||
<li>Some selfmade gibberish</li>
|
||||
</ul>
|
||||
|
||||
<p>Hopefully it is of use to some people :)</p>
|
||||
|
||||
<h3>Thanks</h3>
|
||||
<p>Thanks to Andy for the initial frontend help :)</p>
|
||||
<p>
|
||||
Thanks to Andy for the initial frontend help :)
|
||||
</p>
|
||||
|
||||
<h3>Regards</h3>
|
||||
<p>
|
||||
<a href="https://twitter.com/frikkylikeme" style={hrefStyle}>
|
||||
@frikkylikeme
|
||||
</a>
|
||||
<a href="https://twitter.com/frikkylikeme" style={hrefStyle}>@frikkylikeme</a>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default About;
|
||||
|
||||
+1229
-2079
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,17 @@
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
import React, { useState } from "react";
|
||||
import { makeStyles } from "@material-ui/styles";
|
||||
import React, {useState} from 'react';
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
|
||||
import {
|
||||
CircularProgress,
|
||||
TextField,
|
||||
Button,
|
||||
Paper,
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import {CircularProgress, TextField, Button, Paper, Typography} from '@material-ui/core'
|
||||
|
||||
const bodyDivStyle = {
|
||||
margin: "auto",
|
||||
marginTop: "100px",
|
||||
width: "500px",
|
||||
};
|
||||
}
|
||||
|
||||
const surfaceColor = "#27292D";
|
||||
const inputColor = "#383B40";
|
||||
const surfaceColor = "#27292D"
|
||||
const inputColor = "#383B40"
|
||||
|
||||
const boxStyle = {
|
||||
paddingLeft: "30px",
|
||||
@@ -25,16 +19,16 @@ const boxStyle = {
|
||||
paddingBottom: "30px",
|
||||
paddingTop: "30px",
|
||||
backgroundColor: surfaceColor,
|
||||
};
|
||||
}
|
||||
|
||||
const useStyles = makeStyles({
|
||||
notchedOutline: {
|
||||
borderColor: "#f85a3e !important",
|
||||
borderColor: "#f85a3e !important"
|
||||
},
|
||||
});
|
||||
|
||||
const AdminAccount = (props) => {
|
||||
const { globalUrl, isLoaded, isLoggedIn } = props;
|
||||
const AdminAccount = props => {
|
||||
const { globalUrl, isLoaded, isLoggedIn, } = props;
|
||||
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
@@ -42,89 +36,89 @@ const AdminAccount = (props) => {
|
||||
const [loginLoading, setLoginLoading] = useState(false);
|
||||
|
||||
// Used to swap from login to register. True = login, false = register
|
||||
const register = true;
|
||||
const register = true
|
||||
|
||||
const classes = useStyles();
|
||||
// Error messages etc
|
||||
const [loginInfo, setLoginInfo] = useState("");
|
||||
|
||||
const handleValidateForm = () => {
|
||||
return username.length > 1 && password.length > 1;
|
||||
};
|
||||
return (username.length > 1 && password.length > 1);
|
||||
}
|
||||
|
||||
if (isLoggedIn === true) {
|
||||
window.location.pathname = "/workflows";
|
||||
window.location.pathname = "/workflows"
|
||||
}
|
||||
|
||||
const checkAdmin = () => {
|
||||
const url = globalUrl + "/api/v1/checkusers";
|
||||
const url = globalUrl+'/api/v1/checkusers';
|
||||
fetch(url, {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
if (responseJson["success"] === false) {
|
||||
setLoginInfo(responseJson["reason"]);
|
||||
setLoginInfo(responseJson["reason"])
|
||||
} else {
|
||||
if (responseJson.reason === "redirect") {
|
||||
window.location.pathname = "/login";
|
||||
window.location.pathname = "/login"
|
||||
}
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setLoginInfo("Error in userdata: ", error);
|
||||
});
|
||||
};
|
||||
.catch(error => {
|
||||
setLoginInfo("Error in userdata: ", error)
|
||||
})
|
||||
}
|
||||
|
||||
if (firstRequest) {
|
||||
setFirstRequest(false);
|
||||
checkAdmin();
|
||||
setFirstRequest(false)
|
||||
checkAdmin()
|
||||
}
|
||||
|
||||
const onSubmit = (e) => {
|
||||
setLoginLoading(true);
|
||||
e.preventDefault();
|
||||
setLoginLoading(true)
|
||||
e.preventDefault()
|
||||
// FIXME - add some check here ROFL
|
||||
|
||||
// Just use this one?
|
||||
var data = { username: username, password: password };
|
||||
var baseurl = globalUrl;
|
||||
const url = baseurl + "/api/v1/register";
|
||||
var data = {"username": username, "password": password}
|
||||
var baseurl = globalUrl
|
||||
const url = baseurl+'/api/v1/register';
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
setLoginLoading(false);
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
setLoginLoading(false)
|
||||
if (responseJson["success"] === false) {
|
||||
setLoginInfo(responseJson["reason"]);
|
||||
setLoginInfo(responseJson["reason"])
|
||||
} else {
|
||||
setLoginInfo("Successful register :)");
|
||||
window.location.pathname = "/login";
|
||||
setLoginInfo("Successful register :)")
|
||||
window.location.pathname = "/login"
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setLoginLoading(false);
|
||||
setLoginInfo("Error in userdata: ", error);
|
||||
.catch(error => {
|
||||
setLoginLoading(false)
|
||||
setLoginInfo("Error in userdata: ", error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const onChangeUser = (e) => {
|
||||
setUsername(e.target.value);
|
||||
};
|
||||
setUsername(e.target.value)
|
||||
}
|
||||
|
||||
const onChangePass = (e) => {
|
||||
setPassword(e.target.value);
|
||||
};
|
||||
setPassword(e.target.value)
|
||||
}
|
||||
|
||||
//const onClickRegister = () => {
|
||||
// if (props.location.pathname === "/login") {
|
||||
@@ -137,29 +131,26 @@ const AdminAccount = (props) => {
|
||||
//}
|
||||
|
||||
//var loginChange = register ? (<div><p onClick={setLoginCheck(false)}>Want to register? Click here.</p></div>) : (<div><p onClick={setLoginCheck(true)}>Go back to login? Click here.</p></div>);
|
||||
var formtitle = register ? <div>Login</div> : <div>Register</div>;
|
||||
var formtitle = register ? <div>Login</div> : <div>Register</div>
|
||||
|
||||
formtitle = "Create administrator account";
|
||||
formtitle = "Create administrator account"
|
||||
|
||||
const basedata = (
|
||||
const basedata =
|
||||
<div style={bodyDivStyle}>
|
||||
<Paper style={boxStyle}>
|
||||
<form
|
||||
onSubmit={onSubmit}
|
||||
style={{ color: "white", margin: "15px 15px 15px 15px" }}
|
||||
>
|
||||
<form onSubmit={onSubmit} style={{color: "white", margin: "15px 15px 15px 15px"}}>
|
||||
<h2>{formtitle}</h2>
|
||||
Username
|
||||
<div>
|
||||
<TextField
|
||||
color="primary"
|
||||
style={{ backgroundColor: inputColor }}
|
||||
style={{backgroundColor: inputColor}}
|
||||
autoFocus
|
||||
InputProps={{
|
||||
classes: {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
style:{
|
||||
height: "50px",
|
||||
color: "white",
|
||||
fontSize: "1em",
|
||||
@@ -179,12 +170,12 @@ const AdminAccount = (props) => {
|
||||
<div>
|
||||
<TextField
|
||||
color="primary"
|
||||
style={{ backgroundColor: inputColor }}
|
||||
style={{backgroundColor: inputColor,}}
|
||||
InputProps={{
|
||||
classes: {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
style:{
|
||||
height: "50px",
|
||||
color: "white",
|
||||
fontSize: "1em",
|
||||
@@ -201,33 +192,32 @@ const AdminAccount = (props) => {
|
||||
onChange={onChangePass}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: "flex", marginTop: "15px" }}>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
type="submit"
|
||||
style={{ flex: "1", marginRight: "5px" }}
|
||||
disabled={!handleValidateForm() || loginLoading}
|
||||
>
|
||||
{loginLoading ? (
|
||||
<CircularProgress
|
||||
color="secondary"
|
||||
style={{ color: "white" }}
|
||||
/>
|
||||
) : (
|
||||
"SUBMIT"
|
||||
)}
|
||||
<div style={{display: "flex", marginTop: "15px"}}>
|
||||
<Button color="primary" variant="contained" type="submit" style={{flex: "1", marginRight: "5px"}} disabled={!handleValidateForm() || loginLoading}>
|
||||
{loginLoading ? <CircularProgress color="secondary" style={{color: "white",}} /> : "SUBMIT"}
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
<div style={{marginTop: "10px"}}>
|
||||
{loginInfo}
|
||||
</div>
|
||||
<div style={{ marginTop: "10px" }}>{loginInfo}</div>
|
||||
</form>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
|
||||
const loadedCheck = isLoaded ? <div>{basedata}</div> : <div></div>;
|
||||
const loadedCheck = isLoaded ?
|
||||
<div>
|
||||
{basedata}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AdminAccount;
|
||||
|
||||
+3888
-6909
File diff suppressed because one or more lines are too long
+1606
-2707
File diff suppressed because it is too large
Load Diff
+686
-1231
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,19 @@
|
||||
import React, { useState } from "react";
|
||||
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 Paper from '@material-ui/core/Paper';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
|
||||
import { useTheme } from "@material-ui/core/styles";
|
||||
import { useTheme } from '@material-ui/core/styles';
|
||||
|
||||
const bodyDivStyle = {
|
||||
margin: "auto",
|
||||
textAlign: "center",
|
||||
width: "900px",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Should be different if logged in :|
|
||||
const Contact = (props) => {
|
||||
@@ -30,12 +31,12 @@ const Contact = (props) => {
|
||||
paddingTop: "30px",
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
};
|
||||
flexDirection: "column"
|
||||
}
|
||||
|
||||
const bodyTextStyle = {
|
||||
color: "#ffffff",
|
||||
};
|
||||
}
|
||||
|
||||
const [firstname, setFirstname] = useState("");
|
||||
const [lastname, setLastname] = useState("");
|
||||
@@ -49,41 +50,39 @@ const Contact = (props) => {
|
||||
|
||||
const submitContact = () => {
|
||||
const data = {
|
||||
firstname: firstname,
|
||||
lastname: lastname,
|
||||
title: title,
|
||||
companyname: companyname,
|
||||
email: email,
|
||||
phone: phone,
|
||||
message: message,
|
||||
};
|
||||
console.log(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",
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((response) => {
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
if (response.success === true) {
|
||||
setFormMessage(response.message);
|
||||
setFormMessage(response.message)
|
||||
} else {
|
||||
setFormMessage(
|
||||
"Something went wrong. Please contact frikky@shuffler.io."
|
||||
);
|
||||
setFormMessage("Something went wrong. Please contact frikky@shuffler.io.")
|
||||
}
|
||||
console.log(response);
|
||||
console.log(response)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Random names for type & autoComplete. Didn't research :^)
|
||||
const landingpageDataBrowser = (
|
||||
const landingpageDataBrowser =
|
||||
<div>
|
||||
<div style={bodyTextStyle}>
|
||||
<h3 style={{ color: "#f85a3e" }}>Contact us</h3>
|
||||
@@ -95,11 +94,7 @@ const Contact = (props) => {
|
||||
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
|
||||
<TextField
|
||||
required
|
||||
style={{
|
||||
flex: "1",
|
||||
marginRight: "15px",
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
}}
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
@@ -113,14 +108,10 @@ const Contact = (props) => {
|
||||
autoComplete="firstname"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setFirstname(e.target.value)}
|
||||
onChange={e => setFirstname(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
style={{
|
||||
flex: "1",
|
||||
marginLeft: "15px",
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
}}
|
||||
style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
@@ -134,16 +125,12 @@ const Contact = (props) => {
|
||||
autoComplete="lastname"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setLastname(e.target.value)}
|
||||
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,
|
||||
}}
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
@@ -157,14 +144,10 @@ const Contact = (props) => {
|
||||
autoComplete="jobtitle"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
onChange={e => setTitle(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
style={{
|
||||
flex: "1",
|
||||
marginLeft: "15px",
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
}}
|
||||
style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
@@ -178,17 +161,13 @@ const Contact = (props) => {
|
||||
autoComplete="companyname"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setCompanyname(e.target.value)}
|
||||
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,
|
||||
}}
|
||||
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
@@ -202,14 +181,10 @@ const Contact = (props) => {
|
||||
autoComplete="email"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
style={{
|
||||
flex: "1",
|
||||
marginLeft: "15px",
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
}}
|
||||
style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
|
||||
InputProps={{
|
||||
style: {
|
||||
color: "white",
|
||||
@@ -223,7 +198,7 @@ const Contact = (props) => {
|
||||
autoComplete="phone"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
onChange={e => setPhone(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
@@ -245,7 +220,7 @@ const Contact = (props) => {
|
||||
id="filled-multiline-static"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
onChange={e => setMessage(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
@@ -261,9 +236,8 @@ const Contact = (props) => {
|
||||
</Paper>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const landingpageDataMobile = (
|
||||
const landingpageDataMobile =
|
||||
<div style={{ paddingBottom: "50px" }}>
|
||||
<div style={{ color: "white", textAlign: "center" }}>
|
||||
<h3 style={{ color: "#f85a3e" }}>Contact us</h3>
|
||||
@@ -289,7 +263,7 @@ const Contact = (props) => {
|
||||
autoComplete="firstname"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setFirstname(e.target.value)}
|
||||
onChange={e => setFirstname(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
|
||||
@@ -309,7 +283,7 @@ const Contact = (props) => {
|
||||
autoComplete="email"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
@@ -331,7 +305,7 @@ const Contact = (props) => {
|
||||
id="filled-multiline-static"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
onChange={e => setMessage(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
@@ -347,19 +321,25 @@ const Contact = (props) => {
|
||||
</Paper>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const loadedCheck = isLoaded ? (
|
||||
|
||||
const loadedCheck = isLoaded ?
|
||||
<div>
|
||||
<BrowserView>
|
||||
<div style={bodyDivStyle}>{landingpageDataBrowser}</div>
|
||||
</BrowserView>
|
||||
<MobileView>{landingpageDataMobile}</MobileView>
|
||||
<MobileView>
|
||||
{landingpageDataMobile}
|
||||
</MobileView>
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
);
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Contact;
|
||||
|
||||
+113
-116
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useInterval } from "react-powerhooks";
|
||||
import React, {useState} from 'react';
|
||||
import { useInterval } from 'react-powerhooks';
|
||||
// nodejs library that concatenates classes
|
||||
import classNames from "classnames";
|
||||
// react plugin used to create charts
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
Table,
|
||||
Row,
|
||||
Col,
|
||||
UncontrolledTooltip,
|
||||
UncontrolledTooltip
|
||||
} from "reactstrap";
|
||||
|
||||
// core components
|
||||
@@ -34,56 +34,56 @@ import {
|
||||
chartExample1,
|
||||
chartExample2,
|
||||
chartExample3,
|
||||
chartExample4,
|
||||
chartExample4
|
||||
} from "../charts.js";
|
||||
|
||||
// This is the start of a dashboard that can be used.
|
||||
// What data do we fill in here? Idk
|
||||
const Dashboard = (props) => {
|
||||
const { globalUrl } = props;
|
||||
const alert = useAlert();
|
||||
const alert = useAlert()
|
||||
const [bigChartData, setBgChartData] = useState("data1");
|
||||
const [dayAmount, setDayAmount] = useState(7);
|
||||
const [firstRequest, setFirstRequest] = useState(true);
|
||||
const [stats, setStats] = useState({});
|
||||
const [changeme, setChangeme] = useState("");
|
||||
const [statsRan, setStatsRan] = useState(false);
|
||||
const [stats, setStats] = useState({})
|
||||
const [changeme, setChangeme] = useState("")
|
||||
const [statsRan, setStatsRan] = useState(false)
|
||||
|
||||
document.title = "Shuffle - dashboard";
|
||||
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];
|
||||
document.title = "Shuffle - dashboard"
|
||||
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]
|
||||
|
||||
const fetchdata = (stats_id) => {
|
||||
fetch(globalUrl + "/api/v1/stats/" + stats_id, {
|
||||
method: "GET",
|
||||
fetch(globalUrl+"/api/v1/stats/"+stats_id, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for " + stats_id);
|
||||
console.log("Status not 200 for "+stats_id)
|
||||
}
|
||||
|
||||
return response.json();
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
stats[stats_id] = responseJson;
|
||||
setStats(stats);
|
||||
stats[stats_id] = responseJson
|
||||
setStats(stats)
|
||||
// Used to force updates
|
||||
setChangeme(stats_id);
|
||||
setChangeme(stats_id)
|
||||
})
|
||||
.catch((error) => {
|
||||
alert.error("ERROR: " + error.toString());
|
||||
.catch(error => {
|
||||
alert.error("ERROR: "+error.toString())
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
let chart1_2_options = {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false,
|
||||
display: false
|
||||
},
|
||||
tooltips: {
|
||||
backgroundColor: "#f5f5f5",
|
||||
@@ -93,7 +93,7 @@ const Dashboard = (props) => {
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest",
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
@@ -103,15 +103,15 @@ const Dashboard = (props) => {
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: "rgba(29,140,248,0.0)",
|
||||
zeroLineColor: "transparent",
|
||||
zeroLineColor: "transparent"
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 60,
|
||||
suggestedMax: 125,
|
||||
padding: 20,
|
||||
fontColor: "#9a9a9a",
|
||||
},
|
||||
},
|
||||
fontColor: "#9a9a9a"
|
||||
}
|
||||
}
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
@@ -119,19 +119,19 @@ const Dashboard = (props) => {
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: "rgba(29,140,248,0.1)",
|
||||
zeroLineColor: "transparent",
|
||||
zeroLineColor: "transparent"
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#9a9a9a",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
fontColor: "#9a9a9a"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
const dayGraph = {
|
||||
data: (canvas) => {
|
||||
data: canvas => {
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);
|
||||
@@ -159,12 +159,12 @@ const Dashboard = (props) => {
|
||||
pointHoverBorderWidth: 15,
|
||||
pointRadius: 4,
|
||||
data: dayGraphData,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
options: chart1_2_options,
|
||||
};
|
||||
}
|
||||
|
||||
// All these are currently tracked.
|
||||
const variables = [
|
||||
@@ -180,29 +180,29 @@ const Dashboard = (props) => {
|
||||
"total_workflows",
|
||||
"total_workflow_actions",
|
||||
"total_workflow_triggers",
|
||||
];
|
||||
]
|
||||
|
||||
const runUpdate = () => {
|
||||
for (var key in variables) {
|
||||
fetchdata(variables[key]);
|
||||
fetchdata(variables[key])
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Refresh every 60 seconds
|
||||
const autoUpdate = 60000;
|
||||
const autoUpdate = 60000
|
||||
const { start, stop } = useInterval({
|
||||
duration: autoUpdate,
|
||||
startImmediate: false,
|
||||
callback: () => {
|
||||
runUpdate();
|
||||
},
|
||||
});
|
||||
runUpdate()
|
||||
}
|
||||
})
|
||||
|
||||
if (firstRequest) {
|
||||
console.log("HELO");
|
||||
setFirstRequest(false);
|
||||
start();
|
||||
runUpdate();
|
||||
console.log("HELO")
|
||||
setFirstRequest(false)
|
||||
start()
|
||||
runUpdate()
|
||||
} else if (!statsRan) {
|
||||
// FIXME: Run this under runUpdate schedule?
|
||||
// 1. Fix labels in dayGraphy.data
|
||||
@@ -211,102 +211,90 @@ const Dashboard = (props) => {
|
||||
// Every time there's an update :)
|
||||
|
||||
// This should probably be done in the backend.. bleh
|
||||
if (
|
||||
stats["workflow_executions"] !== undefined &&
|
||||
stats["workflow_executions"] !== null &&
|
||||
stats["workflow_executions"].data !== undefined
|
||||
) {
|
||||
setStatsRan(true);
|
||||
if (stats["workflow_executions"] !== undefined && stats["workflow_executions"] !== null && stats["workflow_executions"].data !== undefined) {
|
||||
setStatsRan(true)
|
||||
//console.log("NEW DATA?: ", stats)
|
||||
console.log("SET WORKFLOW: ", stats["workflow_executions"]);
|
||||
console.log('SET WORKFLOW: ', stats["workflow_executions"])
|
||||
//var curday = startDate.getDate()
|
||||
|
||||
// Index = what day are we on
|
||||
|
||||
// 0 = today
|
||||
var newDayGraphLabels = [];
|
||||
var newDayGraphData = [];
|
||||
var newDayGraphLabels = []
|
||||
var newDayGraphData = []
|
||||
for (var i = dayAmount; i > 0; i--) {
|
||||
var enddate = new Date();
|
||||
enddate.setDate(-i);
|
||||
enddate.setHours(23, 59, 59, 999);
|
||||
var enddate = new Date()
|
||||
enddate.setDate(-i)
|
||||
enddate.setHours(23,59,59,999)
|
||||
|
||||
var startdate = new Date();
|
||||
startdate.setDate(-i);
|
||||
startdate.setHours(0, 0, 0, 0);
|
||||
var startdate = new Date()
|
||||
startdate.setDate(-i)
|
||||
startdate.setHours(0,0,0,0)
|
||||
|
||||
var endtime = enddate.getTime() / 1000;
|
||||
var starttime = startdate.getTime() / 1000;
|
||||
var endtime = enddate.getTime()/1000
|
||||
var starttime = startdate.getTime()/1000
|
||||
|
||||
console.log(
|
||||
"START: ",
|
||||
starttime,
|
||||
"END: ",
|
||||
endtime,
|
||||
"Data: ",
|
||||
stats["workflow_executions"]
|
||||
);
|
||||
console.log("START: ", starttime, "END: ", endtime, "Data: ", stats["workflow_executions"])
|
||||
for (var key in stats["workflow_executions"].data) {
|
||||
const item = stats["workflow_executions"]["data"][key];
|
||||
console.log("ITEM: ", item.timestamp, endtime);
|
||||
console.log(endtime - starttime);
|
||||
if (
|
||||
endtime - starttime > endtime - item.timestamp &&
|
||||
endtime.timestamp >= 0
|
||||
) {
|
||||
console.log("HIT? ");
|
||||
const item = stats["workflow_executions"]["data"][key]
|
||||
console.log("ITEM: ", item.timestamp, endtime)
|
||||
console.log(endtime-starttime)
|
||||
if (endtime-starttime > endtime-item.timestamp && endtime.timestamp >= 0) {
|
||||
console.log("HIT? ")
|
||||
}
|
||||
console.log(item.timestamp - endtime);
|
||||
console.log(item.timestamp-endtime)
|
||||
//console.log(item.timestamp-endtime)
|
||||
break;
|
||||
break
|
||||
if (item.timestamp > endtime && item.timestamp < starttime) {
|
||||
if (newDayGraphData[i - 1] === undefined) {
|
||||
newDayGraphData[i - 1] = 1;
|
||||
if (newDayGraphData[i-1] === undefined) {
|
||||
newDayGraphData[i-1] = 1
|
||||
} else {
|
||||
newDayGraphData[i - 1] += 1;
|
||||
newDayGraphData[i-1] += 1
|
||||
}
|
||||
|
||||
//break
|
||||
}
|
||||
}
|
||||
|
||||
newDayGraphLabels.push(i);
|
||||
newDayGraphLabels.push(i)
|
||||
}
|
||||
|
||||
console.log(newDayGraphLabels);
|
||||
console.log(newDayGraphData);
|
||||
console.log(newDayGraphLabels)
|
||||
console.log(newDayGraphData)
|
||||
}
|
||||
}
|
||||
|
||||
const newdata =
|
||||
Object.getOwnPropertyNames(stats).length > 0 ? (
|
||||
const newdata = Object.getOwnPropertyNames(stats).length > 0 ?
|
||||
<div>
|
||||
Autoupdate every {autoUpdate / 1000} seconds
|
||||
{variables.map((data) => {
|
||||
Autoupdate every {autoUpdate/1000} seconds
|
||||
{variables.map(data => {
|
||||
if (stats[data] === undefined || stats[data] === null) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
if (stats[data].total === undefined) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{data}: {stats[data].total}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : null;
|
||||
: null
|
||||
|
||||
const data = (
|
||||
const data =
|
||||
<div className="content">
|
||||
{newdata}
|
||||
<Row>
|
||||
<Col xs="12">
|
||||
<div className="chart-area">
|
||||
<Line data={dayGraph.data} options={dayGraph.options} />
|
||||
<Line
|
||||
data={dayGraph.data}
|
||||
options={dayGraph.options}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs="12">
|
||||
@@ -325,7 +313,7 @@ const Dashboard = (props) => {
|
||||
<Button
|
||||
tag="label"
|
||||
className={classNames("btn-simple", {
|
||||
active: bigChartData === "data1",
|
||||
active: bigChartData === "data1"
|
||||
})}
|
||||
color="info"
|
||||
id="0"
|
||||
@@ -351,11 +339,15 @@ const Dashboard = (props) => {
|
||||
size="sm"
|
||||
tag="label"
|
||||
className={classNames("btn-simple", {
|
||||
active: bigChartData === "data2",
|
||||
active: bigChartData === "data2"
|
||||
})}
|
||||
onClick={() => setBgChartData("data2")}
|
||||
>
|
||||
<input className="d-none" name="options" type="radio" />
|
||||
<input
|
||||
className="d-none"
|
||||
name="options"
|
||||
type="radio"
|
||||
/>
|
||||
<span className="d-none d-sm-block d-md-block d-lg-block d-xl-block">
|
||||
Purchases
|
||||
</span>
|
||||
@@ -369,11 +361,15 @@ const Dashboard = (props) => {
|
||||
size="sm"
|
||||
tag="label"
|
||||
className={classNames("btn-simple", {
|
||||
active: bigChartData === "data3",
|
||||
active: bigChartData === "data3"
|
||||
})}
|
||||
onClick={() => setBgChartData("data3")}
|
||||
>
|
||||
<input className="d-none" name="options" type="radio" />
|
||||
<input
|
||||
className="d-none"
|
||||
name="options"
|
||||
type="radio"
|
||||
/>
|
||||
<span className="d-none d-sm-block d-md-block d-lg-block d-xl-block">
|
||||
Sessions
|
||||
</span>
|
||||
@@ -402,7 +398,8 @@ const Dashboard = (props) => {
|
||||
<CardHeader>
|
||||
<h5 className="card-category">Total Shipments</h5>
|
||||
<CardTitle tag="h3">
|
||||
<i className="tim-icons icon-bell-55 text-info" /> 763,215
|
||||
<i className="tim-icons icon-bell-55 text-info" />{" "}
|
||||
763,215
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
@@ -454,13 +451,13 @@ const Dashboard = (props) => {
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
|
||||
const dataWrapper = (
|
||||
<div style={{ maxWidth: 1366, margin: "auto" }}>{data}</div>
|
||||
);
|
||||
const dataWrapper =
|
||||
<div style={{maxWidth: 1366, margin: "auto"}}>
|
||||
{data}
|
||||
</div>
|
||||
|
||||
return dataWrapper;
|
||||
};
|
||||
return dataWrapper
|
||||
}
|
||||
|
||||
export default Dashboard;
|
||||
export default Dashboard
|
||||
|
||||
+186
-332
@@ -1,45 +1,36 @@
|
||||
import React, { useState } from "react";
|
||||
import React, {useState,} from 'react';
|
||||
|
||||
import { useTheme } from "@material-ui/core/styles";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import { BrowserView, MobileView } from "react-device-detect";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useTheme } from '@material-ui/core/styles';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import {BrowserView, MobileView} from "react-device-detect";
|
||||
import {Link} from 'react-router-dom';
|
||||
|
||||
import {
|
||||
Tooltip,
|
||||
Divider,
|
||||
Button,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Typography,
|
||||
Paper,
|
||||
List,
|
||||
} from "@material-ui/core";
|
||||
import { Link as LinkIcon, Edit as EditIcon } from "@material-ui/icons";
|
||||
import {Tooltip, Divider, Button, Menu, MenuItem, Typography, Paper, List} from '@material-ui/core';
|
||||
import {Link as LinkIcon, Edit as EditIcon} from '@material-ui/icons';
|
||||
|
||||
const Body = {
|
||||
maxWidth: "1000px",
|
||||
minWidth: "768px",
|
||||
margin: "auto",
|
||||
maxWidth: '1000px',
|
||||
minWidth: '768px',
|
||||
margin: 'auto',
|
||||
display: "flex",
|
||||
height: "100%",
|
||||
color: "white",
|
||||
//textAlign: "center",
|
||||
};
|
||||
|
||||
const dividerColor = "rgb(225, 228, 232)";
|
||||
const dividerColor = "rgb(225, 228, 232)"
|
||||
const hrefStyle = {
|
||||
color: "rgba(255, 255, 255, 0.40)",
|
||||
textDecoration: "none",
|
||||
};
|
||||
textDecoration: "none"
|
||||
}
|
||||
|
||||
const innerHrefStyle = {
|
||||
color: "rgba(255, 255, 255, 0.75)",
|
||||
textDecoration: "none",
|
||||
};
|
||||
textDecoration: "none"
|
||||
}
|
||||
|
||||
const Docs = (props) => {
|
||||
const { globalUrl, selectedDoc, serverside, isMobile } = props;
|
||||
const { globalUrl, selectedDoc, serverside, isMobile, } = props;
|
||||
|
||||
const theme = useTheme();
|
||||
const [mobile, setMobile] = useState(isMobile === true ? true : false);
|
||||
@@ -49,14 +40,9 @@ const Docs = (props) => {
|
||||
const [, setListLoaded] = useState(false);
|
||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||
const [headingSet, setHeadingSet] = React.useState(false);
|
||||
const [selectedMeta, setSelectedMeta] = React.useState({
|
||||
link: "hello",
|
||||
read_time: 2,
|
||||
});
|
||||
const [selectedMeta, setSelectedMeta] = React.useState({link: "hello", read_time: 2, });
|
||||
const [tocLines, setTocLines] = React.useState([]);
|
||||
const [baseUrl, setBaseUrl] = React.useState(
|
||||
serverside === true ? "" : window.location.href
|
||||
);
|
||||
const [baseUrl, setBaseUrl] = React.useState(serverside === true ? "" : window.location.href)
|
||||
|
||||
function handleClick(event) {
|
||||
setAnchorEl(event.currentTarget);
|
||||
@@ -74,171 +60,158 @@ const Docs = (props) => {
|
||||
paddingTop: 15,
|
||||
height: "80vh",
|
||||
marginTop: 15,
|
||||
};
|
||||
}
|
||||
|
||||
const SideBar = {
|
||||
maxWidth: 250,
|
||||
flex: "1",
|
||||
position: "fixed",
|
||||
};
|
||||
}
|
||||
|
||||
const fetchDocList = () => {
|
||||
fetch(globalUrl + "/api/v1/docs", {
|
||||
method: "GET",
|
||||
fetch(globalUrl+"/api/v1/docs", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success) {
|
||||
setList(responseJson.list);
|
||||
setList(responseJson.list)
|
||||
} else {
|
||||
setList([
|
||||
"# Error loading documentation. Please contact us if this persists.",
|
||||
]);
|
||||
setList(["# Error loading documentation. Please contact us if this persists."])
|
||||
}
|
||||
setListLoaded(true);
|
||||
setListLoaded(true)
|
||||
})
|
||||
.catch((error) => {});
|
||||
};
|
||||
.catch(error => {});
|
||||
}
|
||||
|
||||
const fetchDocs = (docId) => {
|
||||
fetch(globalUrl + "/api/v1/docs/" + docId, {
|
||||
method: "GET",
|
||||
fetch(globalUrl+"/api/v1/docs/"+docId, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success) {
|
||||
setData(responseJson.reason);
|
||||
document.title = "Shuffle " + docId + " documentation";
|
||||
setData(responseJson.reason)
|
||||
document.title = "Shuffle "+docId+" documentation"
|
||||
|
||||
if (responseJson.meta !== undefined) {
|
||||
setSelectedMeta(responseJson.meta);
|
||||
setSelectedMeta(responseJson.meta)
|
||||
}
|
||||
|
||||
//console.log("TOC list: ", responseJson.reason)
|
||||
if (
|
||||
responseJson.reason !== undefined &&
|
||||
responseJson.reason !== null
|
||||
) {
|
||||
const splitkey = responseJson.reason.split("\n");
|
||||
var innerTocLines = [];
|
||||
var record = false;
|
||||
if (responseJson.reason !== undefined && responseJson.reason !== null) {
|
||||
const splitkey = responseJson.reason.split("\n")
|
||||
var innerTocLines = []
|
||||
var record = false
|
||||
for (var key in splitkey) {
|
||||
const line = splitkey[key];
|
||||
const line = splitkey[key]
|
||||
//console.log("Line: ", line)
|
||||
if (line.toLowerCase().includes("table of contents")) {
|
||||
record = true;
|
||||
continue;
|
||||
record = true
|
||||
continue
|
||||
}
|
||||
|
||||
if (record && line.length < 3) {
|
||||
record = false;
|
||||
record = false
|
||||
}
|
||||
|
||||
if (record) {
|
||||
const parsedline = line.split("](");
|
||||
const parsedline = line.split("](")
|
||||
if (parsedline.length > 1) {
|
||||
parsedline[0] = parsedline[0].replaceAll("*", "");
|
||||
parsedline[0] = parsedline[0].replaceAll("[", "");
|
||||
parsedline[0] = parsedline[0].replaceAll("]", "");
|
||||
parsedline[0] = parsedline[0].replaceAll("(", "");
|
||||
parsedline[0] = parsedline[0].replaceAll(")", "");
|
||||
parsedline[0] = parsedline[0].trim();
|
||||
parsedline[0] = parsedline[0].replaceAll("*", "")
|
||||
parsedline[0] = parsedline[0].replaceAll("[", "")
|
||||
parsedline[0] = parsedline[0].replaceAll("]", "")
|
||||
parsedline[0] = parsedline[0].replaceAll("(", "")
|
||||
parsedline[0] = parsedline[0].replaceAll(")", "")
|
||||
parsedline[0] = parsedline[0].trim()
|
||||
|
||||
parsedline[1] = parsedline[1].replaceAll("*", "");
|
||||
parsedline[1] = parsedline[1].replaceAll("[", "");
|
||||
parsedline[1] = parsedline[1].replaceAll("]", "");
|
||||
parsedline[1] = parsedline[1].replaceAll(")", "");
|
||||
parsedline[1] = parsedline[1].replaceAll("(", "");
|
||||
parsedline[1] = parsedline[1].trim();
|
||||
parsedline[1] = parsedline[1].replaceAll("*", "")
|
||||
parsedline[1] = parsedline[1].replaceAll("[", "")
|
||||
parsedline[1] = parsedline[1].replaceAll("]", "")
|
||||
parsedline[1] = parsedline[1].replaceAll(")", "")
|
||||
parsedline[1] = parsedline[1].replaceAll("(", "")
|
||||
parsedline[1] = parsedline[1].trim()
|
||||
//console.log(parsedline[0], parsedline[1])
|
||||
|
||||
innerTocLines.push({
|
||||
text: parsedline[0],
|
||||
link: parsedline[1],
|
||||
});
|
||||
"text": parsedline[0],
|
||||
"link": parsedline[1]
|
||||
})
|
||||
} else {
|
||||
console.log("Bad line for parsing: ", line);
|
||||
console.log("Bad line for parsing: ", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTocLines(innerTocLines);
|
||||
setTocLines(innerTocLines)
|
||||
}
|
||||
} else {
|
||||
setData("# Error\nThis page doesn't exist.");
|
||||
setData("# Error\nThis page doesn't exist.")
|
||||
}
|
||||
})
|
||||
.catch((error) => {});
|
||||
};
|
||||
.catch(error => {});
|
||||
}
|
||||
|
||||
if (firstrequest) {
|
||||
setFirstrequest(false);
|
||||
setFirstrequest(false)
|
||||
if (!serverside) {
|
||||
if (window.innerWidth < 768) {
|
||||
setMobile(true);
|
||||
setMobile(true)
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedDoc !== undefined) {
|
||||
setData(selectedDoc.reason);
|
||||
setList(selectedDoc.list);
|
||||
setListLoaded(true);
|
||||
setData(selectedDoc.reason)
|
||||
setList(selectedDoc.list)
|
||||
setListLoaded(true)
|
||||
} else {
|
||||
if (!serverside) {
|
||||
fetchDocList();
|
||||
fetchDocs(props.match.params.key);
|
||||
fetchDocList()
|
||||
fetchDocs(props.match.params.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handles search-based changes that origin from outside this file
|
||||
if (serverside !== true && window.location.href !== baseUrl) {
|
||||
setBaseUrl(window.location.href);
|
||||
fetchDocs(props.match.params.key);
|
||||
setBaseUrl(window.location.href)
|
||||
fetchDocs(props.match.params.key)
|
||||
}
|
||||
|
||||
const parseElementScroll = () => {
|
||||
const offset = 45;
|
||||
var parent = document.getElementById("markdown_wrapper_outer");
|
||||
const offset = 45
|
||||
var parent = document.getElementById("markdown_wrapper_outer")
|
||||
if (parent !== null) {
|
||||
//console.log("IN PARENT")
|
||||
var elements = parent.getElementsByTagName("h2");
|
||||
var elements = parent.getElementsByTagName('h2')
|
||||
|
||||
const name = window.location.hash
|
||||
.slice(1, window.location.hash.lenth)
|
||||
.toLowerCase()
|
||||
.split("%20")
|
||||
.join(" ")
|
||||
.split("_")
|
||||
.join(" ")
|
||||
.split("-")
|
||||
.join(" ");
|
||||
const name = window.location.hash.slice(1, window.location.hash.lenth).toLowerCase().split("%20").join(" ").split("_").join(" ").split("-").join(" ")
|
||||
|
||||
//console.log(name)
|
||||
var found = false;
|
||||
var found = false
|
||||
for (var key in elements) {
|
||||
const element = elements[key];
|
||||
const element = elements[key]
|
||||
if (element.innerHTML === undefined) {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
// Fix location..
|
||||
if (element.innerHTML.toLowerCase() === name) {
|
||||
//console.log(element.offsetTop)
|
||||
element.scrollIntoView({ behavior: "smooth" });
|
||||
element.scrollIntoView({behavior: "smooth"})
|
||||
//element.scrollTo({
|
||||
// top: element.offsetTop+offset,
|
||||
// behavior: "smooth"
|
||||
//})
|
||||
found = true;
|
||||
found = true
|
||||
//element.scrollTo({
|
||||
// top: element.offsetTop-100,
|
||||
// behavior: "smooth"
|
||||
@@ -248,23 +221,23 @@ const Docs = (props) => {
|
||||
|
||||
// H#
|
||||
if (!found) {
|
||||
elements = parent.getElementsByTagName("h3");
|
||||
elements = parent.getElementsByTagName('h3')
|
||||
//console.log("NAMe: ", name)
|
||||
found = false;
|
||||
found = false
|
||||
for (key in elements) {
|
||||
const element = elements[key];
|
||||
const element = elements[key]
|
||||
if (element.innerHTML === undefined) {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
// Fix location..
|
||||
if (element.innerHTML.toLowerCase() === name) {
|
||||
element.scrollIntoView({ behavior: "smooth" });
|
||||
element.scrollIntoView({behavior: "smooth"})
|
||||
//element.scrollTo({
|
||||
// top: element.offsetTop-offset,
|
||||
// behavior: "smooth"
|
||||
//})
|
||||
found = true;
|
||||
found = true
|
||||
//element.scrollTo({
|
||||
// top: element.offsetTop-100,
|
||||
// behavior: "smooth"
|
||||
@@ -284,10 +257,10 @@ const Docs = (props) => {
|
||||
// this.scrollDiv.current.scrollIntoView({ behavior: 'smooth' });
|
||||
|
||||
//$(".parent").find("h2:contains('Statistics')").parent();
|
||||
};
|
||||
}
|
||||
|
||||
if (serverside !== true && window.location.hash.length > 0) {
|
||||
parseElementScroll();
|
||||
parseElementScroll()
|
||||
}
|
||||
|
||||
const markdownStyle = {
|
||||
@@ -297,155 +270,78 @@ const Docs = (props) => {
|
||||
overflow: "hidden",
|
||||
paddingBottom: 200,
|
||||
marginLeft: mobile ? 0 : 275,
|
||||
};
|
||||
}
|
||||
|
||||
function OuterLink(props) {
|
||||
if (props.href.includes("http") || props.href.includes("mailto")) {
|
||||
return (
|
||||
<a
|
||||
href={props.href}
|
||||
style={{ color: "#f85a3e", textDecoration: "none" }}
|
||||
>
|
||||
{props.children}
|
||||
</a>
|
||||
);
|
||||
return <a href={props.href} style={{color: "#f85a3e", textDecoration: "none"}}>{props.children}</a>
|
||||
}
|
||||
return (
|
||||
<Link
|
||||
to={props.href}
|
||||
style={{ color: "#f85a3e", textDecoration: "none" }}
|
||||
>
|
||||
{props.children}
|
||||
</Link>
|
||||
);
|
||||
return <Link to={props.href} style={{color: "#f85a3e", textDecoration: "none"}}>{props.children}</Link>
|
||||
}
|
||||
|
||||
function Img(props) {
|
||||
return <img style={{ maxWidth: "100%" }} alt={props.alt} src={props.src} />;
|
||||
return <img style={{maxWidth: "100%"}} alt={props.alt} src={props.src}/>
|
||||
}
|
||||
|
||||
function CodeHandler(props) {
|
||||
return (
|
||||
<pre
|
||||
style={{
|
||||
padding: 15,
|
||||
minWidth: "50%",
|
||||
maxWidth: "100%",
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
overflowX: "auto",
|
||||
overflowY: "hidden",
|
||||
}}
|
||||
>
|
||||
<code>{props.value}</code>
|
||||
<pre style={{padding: 15, minWidth: "50%", maxWidth: "100%", backgroundColor: theme.palette.inputColor, overflowX: "auto", overflowY: "hidden",}}>
|
||||
<code>
|
||||
{props.value}
|
||||
</code>
|
||||
</pre>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
const Heading = (props) => {
|
||||
const element = React.createElement(
|
||||
`h${props.level}`,
|
||||
{ style: { marginTop: props.level === 1 ? 20 : 50 } },
|
||||
props.children
|
||||
);
|
||||
const [hover, setHover] = useState(false);
|
||||
const element = React.createElement(`h${props.level}`, {style: {marginTop: props.level === 1 ? 20 : 50}}, props.children)
|
||||
const [hover, setHover] = useState(false)
|
||||
|
||||
var extraInfo = "";
|
||||
var extraInfo = ""
|
||||
if (props.level === 1) {
|
||||
extraInfo = (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
padding: 15,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
marginBottom: 30,
|
||||
display: "flex",
|
||||
}}
|
||||
>
|
||||
<div style={{ flex: 3, display: "flex", vAlign: "center" }}>
|
||||
{mobile ? null : (
|
||||
<Typography style={{ display: "inline", marginTop: 6 }}>
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
href={selectedMeta.link}
|
||||
target="_blank"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
>
|
||||
extraInfo =
|
||||
<div style={{backgroundColor: theme.palette.inputColor, padding: 15, borderRadius: theme.palette.borderRadius, marginBottom: 30, display: "flex",}}>
|
||||
<div style={{flex: 3, display: "flex", vAlign: "center",}}>
|
||||
{mobile ? null :
|
||||
<Typography style={{display: "inline", marginTop: 6, }}>
|
||||
<a rel="noopener noreferrer" target="_blank" href={selectedMeta.link} target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>
|
||||
<Button style={{}} variant="outlined">
|
||||
<EditIcon /> Edit
|
||||
</Button>
|
||||
</a>
|
||||
</Typography>
|
||||
)}
|
||||
{mobile ? null : (
|
||||
<div
|
||||
style={{
|
||||
height: "100%",
|
||||
width: 1,
|
||||
backgroundColor: "white",
|
||||
marginLeft: 50,
|
||||
marginRight: 50,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<Typography style={{ display: "inline", marginTop: 11 }}>
|
||||
{selectedMeta.read_time} minute
|
||||
{selectedMeta.read_time === 1 ? "" : "s"} to read
|
||||
}
|
||||
{mobile ? null :
|
||||
<div style={{height: "100%", width: 1, backgroundColor: "white", marginLeft: 50, marginRight: 50, }} />
|
||||
}
|
||||
<Typography style={{display: "inline", marginTop: 11, }}>
|
||||
{selectedMeta.read_time} minute{selectedMeta.read_time === 1 ? "" : "s"} to read
|
||||
</Typography>
|
||||
</div>
|
||||
<div style={{ flex: 2 }}>
|
||||
{mobile ||
|
||||
selectedMeta.contributors === undefined ||
|
||||
selectedMeta.contributors === null ? (
|
||||
""
|
||||
) : (
|
||||
<div style={{ margin: 10, height: "100%", display: "inline" }}>
|
||||
{selectedMeta.contributors.slice(0, 7).map((data, index) => {
|
||||
<div style={{flex: 2}}>
|
||||
{mobile || selectedMeta.contributors === undefined || selectedMeta.contributors === null ? "" :
|
||||
<div style={{margin: 10, height: "100%", display: "inline",}}>
|
||||
{selectedMeta.contributors.slice(0,7).map((data, index) => {
|
||||
return (
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
href={data.url}
|
||||
target="_blank"
|
||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
>
|
||||
<a rel="noopener noreferrer" target="_blank" href={data.url} target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>
|
||||
<Tooltip title={data.url} placement="bottom">
|
||||
<img
|
||||
alt={data.url}
|
||||
src={data.image}
|
||||
style={{
|
||||
marginTop: 5,
|
||||
marginRight: 10,
|
||||
height: 40,
|
||||
borderRadius: 40,
|
||||
}}
|
||||
/>
|
||||
<img alt={data.url} src={data.image} style={{marginTop: 5, marginRight: 10, height: 40, borderRadius: 40, }} />
|
||||
</Tooltip>
|
||||
</a>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography
|
||||
onMouseOver={() => {
|
||||
setHover(true);
|
||||
}}
|
||||
>
|
||||
{props.level !== 1 ? (
|
||||
<Divider
|
||||
style={{
|
||||
width: "90%",
|
||||
marginTop: 40,
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
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"
|
||||
@@ -457,10 +353,11 @@ const Docs = (props) => {
|
||||
*/}
|
||||
{extraInfo}
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
//React.createElement("p", {style: {color: "red", backgroundColor: "blue"}}, this.props.paragraph)
|
||||
|
||||
|
||||
//function unicodeToChar(text) {
|
||||
// return text.replace(/\\u[\dA-F]{4}/gi,
|
||||
// function (match) {
|
||||
@@ -469,71 +366,46 @@ const Docs = (props) => {
|
||||
// );
|
||||
//}
|
||||
|
||||
const postDataBrowser =
|
||||
list === undefined || list === null ? null : (
|
||||
const postDataBrowser = list === undefined || list === null ? null :
|
||||
<div style={Body}>
|
||||
<div style={SideBar}>
|
||||
<Paper style={SidebarPaperStyle}>
|
||||
<List style={{ listStyle: "none", paddingLeft: "0" }}>
|
||||
<List style={{listStyle: "none", paddingLeft: "0", }}>
|
||||
{list.map((data, index) => {
|
||||
const item = data.name;
|
||||
const item = data.name
|
||||
if (item === undefined) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
const path = "/docs/" + item;
|
||||
const newname =
|
||||
item.charAt(0).toUpperCase() +
|
||||
item.substring(1).split("_").join(" ").split("-").join(" ");
|
||||
const itemMatching =
|
||||
props.match.params.key.toLowerCase() === item.toLowerCase();
|
||||
const path = "/docs/"+item
|
||||
const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ").split("-").join(" ")
|
||||
const itemMatching = props.match.params.key.toLowerCase() === item.toLowerCase()
|
||||
//const [tocLines, setTocLines] = React.useState([]);
|
||||
return (
|
||||
<li key={index} style={{ marginTop: 10 }}>
|
||||
<Link
|
||||
key={index}
|
||||
style={hrefStyle}
|
||||
to={path}
|
||||
onClick={() => {
|
||||
setTocLines([]);
|
||||
fetchDocs(item);
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
style={{ color: itemMatching ? "#f86a3e" : "inherit" }}
|
||||
variant="body1"
|
||||
>
|
||||
<b>> {newname}</b>
|
||||
</Typography>
|
||||
<li key={index} style={{marginTop: 10,}}>
|
||||
<Link key={index} style={hrefStyle} to={path} onClick={() => {
|
||||
setTocLines([])
|
||||
fetchDocs(item)
|
||||
}}>
|
||||
<Typography style={{color: itemMatching ? "#f86a3e" : "inherit"}} variant="body1"><b>> {newname}</b></Typography>
|
||||
</Link>
|
||||
{itemMatching &&
|
||||
tocLines !== null &&
|
||||
tocLines !== undefined &&
|
||||
tocLines.length > 0 ? (
|
||||
<div style={{ marginLeft: 5 }}>
|
||||
{itemMatching && tocLines !== null && tocLines !== undefined && tocLines.length > 0 ?
|
||||
<div style={{marginLeft: 5}}>
|
||||
{tocLines.map((data, index) => {
|
||||
//console.log(data)
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={index}
|
||||
style={innerHrefStyle}
|
||||
to={data.link}
|
||||
onClick={() => {}}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
<Link key={index} style={innerHrefStyle} to={data.link} onClick={() => {}}>
|
||||
<Typography variant="body2" style={{cursor: "pointer"}}>
|
||||
- {data.text}
|
||||
</Typography>
|
||||
</Link>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : null}
|
||||
: null}
|
||||
</li>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</Paper>
|
||||
@@ -552,7 +424,6 @@ const Docs = (props) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const mobileStyle = {
|
||||
color: "white",
|
||||
@@ -562,21 +433,15 @@ const Docs = (props) => {
|
||||
backgroundColor: "inherit",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
};
|
||||
}
|
||||
|
||||
const postDataMobile =
|
||||
list === undefined || list === null ? null : (
|
||||
const postDataMobile = list === undefined || list === null ? null :
|
||||
<div style={mobileStyle}>
|
||||
<div>
|
||||
<Button
|
||||
fullWidth
|
||||
aria-controls="simple-menu"
|
||||
aria-haspopup="true"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div style={{ color: "white" }}>More docs</div>
|
||||
<Button fullWidth aria-controls="simple-menu" aria-haspopup="true" variant="outlined" color="primary" onClick={handleClick}>
|
||||
<div style={{color: "white"}}>
|
||||
More docs
|
||||
</div>
|
||||
</Button>
|
||||
<Menu
|
||||
id="simple-menu"
|
||||
@@ -587,26 +452,16 @@ const Docs = (props) => {
|
||||
onClose={handleClose}
|
||||
>
|
||||
{list.map((data, index) => {
|
||||
const item = data.name;
|
||||
const item = data.name
|
||||
if (item === undefined) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
const path = "/docs/" + item;
|
||||
const newname =
|
||||
item.charAt(0).toUpperCase() +
|
||||
item.substring(1).split("_").join(" ").split("-").join(" ");
|
||||
const path = "/docs/"+item
|
||||
const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ").split("-").join(" ")
|
||||
return (
|
||||
<MenuItem
|
||||
key={index}
|
||||
style={{ color: "white" }}
|
||||
onClick={() => {
|
||||
window.location.pathname = path;
|
||||
}}
|
||||
>
|
||||
{newname}
|
||||
</MenuItem>
|
||||
);
|
||||
<MenuItem key={index} style={{color: "white",}} onClick={() => {window.location.pathname = path}}>{newname}</MenuItem>
|
||||
)
|
||||
})}
|
||||
</Menu>
|
||||
</div>
|
||||
@@ -623,25 +478,15 @@ const Docs = (props) => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Divider
|
||||
style={{
|
||||
marginTop: "10px",
|
||||
marginBottom: "10px",
|
||||
backgroundColor: dividerColor,
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
fullWidth
|
||||
aria-controls="simple-menu"
|
||||
aria-haspopup="true"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div style={{ color: "white" }}>More docs</div>
|
||||
</Button>
|
||||
<Divider style={{marginTop: "10px", marginBottom: "10px", backgroundColor: dividerColor}}/>
|
||||
<Button fullWidth aria-controls="simple-menu" aria-haspopup="true" variant="outlined" color="primary" onClick={handleClick}>
|
||||
<div style={{color: "white"}}>
|
||||
More docs
|
||||
</div>
|
||||
);
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
//const imageModal =
|
||||
// <Dialog modal
|
||||
@@ -649,14 +494,23 @@ const Docs = (props) => {
|
||||
// </Dialog>
|
||||
// {imageModal}
|
||||
|
||||
const loadedCheck = (
|
||||
<div>
|
||||
<BrowserView>{postDataBrowser}</BrowserView>
|
||||
<MobileView>{postDataMobile}</MobileView>
|
||||
</div>
|
||||
);
|
||||
|
||||
return <div style={{}}>{loadedCheck}</div>;
|
||||
};
|
||||
const loadedCheck =
|
||||
<div>
|
||||
<BrowserView>
|
||||
{postDataBrowser}
|
||||
</BrowserView>
|
||||
<MobileView>
|
||||
{postDataMobile}
|
||||
</MobileView>
|
||||
</div>
|
||||
|
||||
return (
|
||||
<div style={{}}>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default Docs;
|
||||
|
||||
+505
-691
File diff suppressed because it is too large
Load Diff
+176
-203
@@ -1,13 +1,13 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, {useState, useEffect} from 'react';
|
||||
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import Divider from "@material-ui/core/Divider";
|
||||
import Select from "@material-ui/core/Select";
|
||||
import MenuItem from "@material-ui/core/MenuItem";
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
import Select from '@material-ui/core/Select';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
|
||||
import WebhookImage from "../assets/img/webhook.png";
|
||||
import KafkaImage from "../assets/img/kafka.png";
|
||||
import WebhookImage from '../assets/img/webhook.png';
|
||||
import KafkaImage from '../assets/img/kafka.png';
|
||||
|
||||
import EditWorkflow from "./EditWorkflow";
|
||||
|
||||
@@ -16,165 +16,166 @@ const EditWebhook = (props) => {
|
||||
|
||||
// FIXME
|
||||
//const [webhookData, setWebhookData] = useState(webhooktest)
|
||||
const [webhookData, setWebhookData] = useState({});
|
||||
const [workflows, setWorkflows] = useState([]);
|
||||
const [webhookData, setWebhookData] = useState({})
|
||||
const [workflows, setWorkflows] = useState([])
|
||||
const [firstrequest, setFirstrequest] = React.useState(true);
|
||||
|
||||
const [selectedWorkflows, setSelectedWorkflows] = useState([]);
|
||||
const [selectedWorkflows, setSelectedWorkflows] = useState([])
|
||||
|
||||
const getWorkflows = () => {
|
||||
fetch(globalUrl + "/api/v1/workflows", {
|
||||
method: "GET",
|
||||
fetch(globalUrl+"/api/v1/workflows", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for workflows :O!");
|
||||
console.log("Status not 200 for workflows :O!")
|
||||
}
|
||||
return response.json();
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
setWorkflows(responseJson);
|
||||
setWorkflows(responseJson)
|
||||
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const setWebhook = (inputdata) => {
|
||||
console.log(inputdata);
|
||||
console.log(inputdata)
|
||||
|
||||
fetch(globalUrl + "/api/v1/hooks/" + props.match.params.key, {
|
||||
method: "PUT",
|
||||
fetch(globalUrl+"/api/v1/hooks/"+props.match.params.key, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
body: JSON.stringify(inputdata),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
console.log(responseJson);
|
||||
console.log(responseJson)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const getCurrentWebhook = () => {
|
||||
fetch(globalUrl + "/api/v1/hooks/" + props.match.params.key, {
|
||||
method: "GET",
|
||||
fetch(globalUrl+"/api/v1/hooks/"+props.match.params.key, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200!");
|
||||
window.location.pathname = "webhooks";
|
||||
console.log("Status not 200!")
|
||||
window.location.pathname = "webhooks"
|
||||
}
|
||||
return response.json();
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson.actions === null) {
|
||||
responseJson.actions = [];
|
||||
responseJson.actions = []
|
||||
}
|
||||
|
||||
if (responseJson.transforms === null) {
|
||||
responseJson.transforms = [];
|
||||
responseJson.transforms = []
|
||||
}
|
||||
|
||||
setWebhookData(responseJson);
|
||||
setWebhookData(responseJson)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
//window.location.pathname = "webhooks"
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (firstrequest) {
|
||||
setFirstrequest(false);
|
||||
getCurrentWebhook();
|
||||
setFirstrequest(false)
|
||||
getCurrentWebhook()
|
||||
if (workflows.length <= 0) {
|
||||
getWorkflows();
|
||||
getWorkflows()
|
||||
}
|
||||
}
|
||||
|
||||
// After everything is loaded
|
||||
if (
|
||||
Object.getOwnPropertyNames(webhookData).length > 0 &&
|
||||
webhookData.actions.length > 0 &&
|
||||
workflows.length > 0 &&
|
||||
selectedWorkflows.length === 0
|
||||
) {
|
||||
if (Object.getOwnPropertyNames(webhookData).length > 0 && webhookData.actions.length > 0 && workflows.length > 0 && selectedWorkflows.length === 0) {
|
||||
// Setting startup actions. making like this in case we want other actions
|
||||
var tmpActionWorkflows = [];
|
||||
var tmpActionWorkflows = []
|
||||
for (var key in webhookData.actions) {
|
||||
if (webhookData.actions[key].type === "workflow") {
|
||||
tmpActionWorkflows.push(webhookData.actions[key]);
|
||||
tmpActionWorkflows.push(webhookData.actions[key])
|
||||
}
|
||||
}
|
||||
|
||||
// Fix duplicates... Meh
|
||||
var foundWorkflowIds = [];
|
||||
var tmpWorkflows = [];
|
||||
var foundWorkflowIds = []
|
||||
var tmpWorkflows = []
|
||||
for (key in tmpActionWorkflows) {
|
||||
if (foundWorkflowIds.includes(tmpActionWorkflows[key].id)) {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
for (var subkey in workflows) {
|
||||
if (tmpActionWorkflows[key].id === workflows[subkey]["id_"]) {
|
||||
console.log(tmpActionWorkflows[key].id, workflows[subkey]["id_"]);
|
||||
foundWorkflowIds.push(tmpActionWorkflows[key].id);
|
||||
tmpWorkflows.push(workflows[subkey]);
|
||||
break;
|
||||
console.log(tmpActionWorkflows[key].id, workflows[subkey]["id_"])
|
||||
foundWorkflowIds.push(tmpActionWorkflows[key].id)
|
||||
tmpWorkflows.push(workflows[subkey])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpWorkflows.length > 0) {
|
||||
setSelectedWorkflows(tmpWorkflows);
|
||||
setSelectedWorkflows(tmpWorkflows)
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const hookPicture =
|
||||
Object.getOwnPropertyNames(webhookData).length > 0 &&
|
||||
webhookData.type === "webhook" ? (
|
||||
<img src={WebhookImage} alt="webhook" width="100px" height="100px" />
|
||||
) : (
|
||||
<img src={KafkaImage} alt="MQ" width="100px" height="100px" />
|
||||
);
|
||||
|
||||
const hookPicture = Object.getOwnPropertyNames(webhookData).length > 0 && webhookData.type === "webhook" ?
|
||||
<img
|
||||
src={WebhookImage}
|
||||
alt="webhook"
|
||||
width="100px"
|
||||
height="100px"
|
||||
/>
|
||||
:
|
||||
<img
|
||||
src={KafkaImage}
|
||||
alt="MQ"
|
||||
width="100px"
|
||||
height="100px"
|
||||
/>
|
||||
|
||||
const executeHook = (action) => {
|
||||
fetch(
|
||||
globalUrl + "/api/v1/hooks/" + props.match.params.key + "/" + action,
|
||||
{
|
||||
method: "POST",
|
||||
fetch(globalUrl+"/api/v1/hooks/"+props.match.params.key+"/"+action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
}
|
||||
)
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
setWebhookData({});
|
||||
setWebhookData({})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const headerPaperStyle = {
|
||||
display: "flex",
|
||||
@@ -183,211 +184,183 @@ const EditWebhook = (props) => {
|
||||
margin: "10px 30px 10px 10px",
|
||||
padding: "10px 5px 5px 5px",
|
||||
flexDirection: "column",
|
||||
};
|
||||
}
|
||||
|
||||
// FIXME - add with counter to change the correct one (not just edit)
|
||||
const addNewWorkflow = (event) => {
|
||||
// Verify if it already exists in the array. Returns if it exists
|
||||
for (var key in selectedWorkflows) {
|
||||
var item = selectedWorkflows[key];
|
||||
var item = selectedWorkflows[key]
|
||||
if (item["id_"] === event.target.value["id_"]) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME - make this possible for all accounts
|
||||
if (selectedWorkflows.length === 0) {
|
||||
console.log("ADD FIRST ITEM FOR SELECTEDWORKFLOWS");
|
||||
console.log(event.target.value);
|
||||
console.log("ADD FIRST ITEM FOR SELECTEDWORKFLOWS")
|
||||
console.log(event.target.value)
|
||||
|
||||
// Cleanup previous actions
|
||||
var newActions = [];
|
||||
var newActions = []
|
||||
if (webhookData.actions.length > 0) {
|
||||
for (key in webhookData.actions) {
|
||||
if (
|
||||
webhookData.actions[key].type === "" ||
|
||||
webhookData.actions[key].type === undefined
|
||||
) {
|
||||
continue;
|
||||
if (webhookData.actions[key].type === "" || webhookData.actions[key].type === undefined) {
|
||||
continue
|
||||
}
|
||||
|
||||
newActions.push(webhookData.actions[key]);
|
||||
newActions.push(webhookData.actions[key])
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME - how to stringify this better hurr
|
||||
var formattedWorkflow = {
|
||||
type: "workflow",
|
||||
name: event.target.value.name,
|
||||
id: event.target.value.id_,
|
||||
field: "",
|
||||
};
|
||||
|
||||
// FIXME: patch this n
|
||||
newActions.push(formattedWorkflow);
|
||||
console.log(newActions);
|
||||
|
||||
webhookData.actions = newActions;
|
||||
setWebhook(webhookData);
|
||||
"type": "workflow",
|
||||
"name": event.target.value.name,
|
||||
"id": event.target.value.id_,
|
||||
"field": "",
|
||||
}
|
||||
|
||||
var tmpSelectedWorkflows = [].concat(selectedWorkflows, [
|
||||
event.target.value,
|
||||
]);
|
||||
setSelectedWorkflows(tmpSelectedWorkflows);
|
||||
};
|
||||
// FIXME: patch this n
|
||||
newActions.push(formattedWorkflow)
|
||||
console.log(newActions)
|
||||
|
||||
webhookData.actions = newActions
|
||||
setWebhook(webhookData)
|
||||
}
|
||||
|
||||
var tmpSelectedWorkflows = [].concat(selectedWorkflows, [event.target.value])
|
||||
setSelectedWorkflows(tmpSelectedWorkflows)
|
||||
}
|
||||
|
||||
// FIXME
|
||||
// Create a list with + button
|
||||
// For each, choose the new workflow I wanna add
|
||||
// Current: JUST ONE
|
||||
const selectedWorkflowIds = selectedWorkflows.map((data) => {
|
||||
return data["id_"];
|
||||
});
|
||||
const availableWorkflows = workflows.filter(
|
||||
(data) => !selectedWorkflowIds.includes(data["id_"])
|
||||
);
|
||||
const selectedWorkflowIds = selectedWorkflows.map(data => {return data["id_"]})
|
||||
const availableWorkflows = workflows.filter(data => !selectedWorkflowIds.includes(data["id_"]))
|
||||
|
||||
const WorkflowSelect = (counter) => {
|
||||
if (selectedWorkflows[counter.counter] === undefined) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
console.log(selectedWorkflows[0]);
|
||||
console.log(selectedWorkflows[0]);
|
||||
console.log(selectedWorkflows[0]);
|
||||
console.log(selectedWorkflows[counter.counter]);
|
||||
console.log(selectedWorkflows[counter.counter].name);
|
||||
console.log(selectedWorkflows[0])
|
||||
console.log(selectedWorkflows[0])
|
||||
console.log(selectedWorkflows[0])
|
||||
console.log(selectedWorkflows[counter.counter])
|
||||
console.log(selectedWorkflows[counter.counter].name)
|
||||
return (
|
||||
<div>
|
||||
Workflow select:
|
||||
<Select
|
||||
value={selectedWorkflows[counter.counter].name}
|
||||
onChange={(event) => {
|
||||
addNewWorkflow(event, counter.counter);
|
||||
}}
|
||||
onChange={(event) => {addNewWorkflow(event, counter.counter)}}
|
||||
displayEmpty
|
||||
name="workflow"
|
||||
>
|
||||
{availableWorkflows.map((data) => (
|
||||
<MenuItem key={data.name} value={data} name={data.name}>
|
||||
{data.name}
|
||||
</MenuItem>
|
||||
{availableWorkflows.map(data => (
|
||||
<MenuItem key={data.name} value={data} name={data.name}>{data.name}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const extraWorkflow =
|
||||
workflows.length > 0 && availableWorkflows.length > 0 ? (
|
||||
<WorkflowSelect counter={selectedWorkflows.length} />
|
||||
) : null;
|
||||
const extraWorkflow = workflows.length > 0 && availableWorkflows.length > 0 ?
|
||||
<WorkflowSelect counter={selectedWorkflows.length}/> : null
|
||||
|
||||
const multiWorkflowSelect =
|
||||
workflows.length > 0 && selectedWorkflows.length > 0 ? (
|
||||
const multiWorkflowSelect = workflows.length > 0 && selectedWorkflows.length > 0 ?
|
||||
<div>
|
||||
{selectedWorkflows.map((data, count) => (
|
||||
<WorkflowSelect key={count} counter={count} />
|
||||
<WorkflowSelect key={count} counter={count}/>
|
||||
))}
|
||||
{extraWorkflow}
|
||||
</div>
|
||||
) : (
|
||||
<WorkflowSelect counter={0} />
|
||||
);
|
||||
: <WorkflowSelect counter={0}/>
|
||||
|
||||
const headerInfo =
|
||||
Object.getOwnPropertyNames(webhookData).length > 0 ? (
|
||||
const headerInfo = Object.getOwnPropertyNames(webhookData).length > 0 ?
|
||||
<div>
|
||||
<Paper style={headerPaperStyle}>
|
||||
<div style={{ display: "flex", flex: "1" }}>
|
||||
<div style={{ flex: "1" }}>{hookPicture}</div>
|
||||
<div
|
||||
style={{ display: "flex", flexDirection: "column", flex: "5" }}
|
||||
>
|
||||
<div style={{ flex: "1" }}>
|
||||
<div style={{display: "flex", flex: "1"}}>
|
||||
<div style={{flex: "1"}}>
|
||||
{hookPicture}
|
||||
</div>
|
||||
<div style={{display: "flex", flexDirection: "column", flex: "5"}}>
|
||||
<div style={{flex: "1"}}>
|
||||
<h1>Name: {webhookData.info.name}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ flex: "4" }}>
|
||||
<div style={{flex: "4"}}>
|
||||
Description: {webhookData.info.description}
|
||||
<div>Id: {webhookData.id}</div>
|
||||
<div>Url: {webhookData.info.url}</div>
|
||||
<div>Type: {webhookData.type}</div>
|
||||
<div>Status: {webhookData.status}</div>
|
||||
<div>
|
||||
Id: {webhookData.id}
|
||||
</div>
|
||||
<div>
|
||||
Url: {webhookData.info.url}
|
||||
</div>
|
||||
<div>
|
||||
Type: {webhookData.type}
|
||||
</div>
|
||||
<div>
|
||||
Status: {webhookData.status}
|
||||
</div>
|
||||
<div>
|
||||
CHOOSE ACTIONS:
|
||||
{multiWorkflowSelect}
|
||||
</div>
|
||||
</div>
|
||||
<Divider />
|
||||
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
|
||||
<div style={{ flex: "1" }}>
|
||||
<div style={{flex: "1", display: "flex", flexDirection: "row"}}>
|
||||
<div style={{flex: "1"}}>
|
||||
<Button
|
||||
disabled={
|
||||
webhookData.running === true && webhookData.name !== ""
|
||||
}
|
||||
onClick={() => {
|
||||
executeHook("start");
|
||||
}}
|
||||
style={{
|
||||
left: "50%",
|
||||
top: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
}}
|
||||
disabled={webhookData.running === true && webhookData.name !== ""}
|
||||
onClick={() => {executeHook("start")}}
|
||||
style={{left: "50%", top: "50%", transform: "translate(-50%, -50%)"}}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
>
|
||||
Start {webhookData.type}
|
||||
</Button>
|
||||
>Start {webhookData.type}</Button>
|
||||
</div>
|
||||
<div style={{ flex: "1" }}>
|
||||
<div style={{flex: "1"}}>
|
||||
<Button
|
||||
disabled={webhookData.running === false}
|
||||
onClick={() => {
|
||||
executeHook("stop");
|
||||
}}
|
||||
style={{
|
||||
left: "50%",
|
||||
top: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
}}
|
||||
onClick={() => {executeHook("stop")}}
|
||||
style={{left: "50%", top: "50%", transform: "translate(-50%, -50%)"}}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
>
|
||||
Stop {webhookData.type}
|
||||
</Button>
|
||||
>Stop {webhookData.type}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Paper>
|
||||
</div>
|
||||
) : null;
|
||||
: null
|
||||
|
||||
// FIXME - needs refresh every time you add a new workflow
|
||||
const workflowdata =
|
||||
Object.getOwnPropertyNames(webhookData).length > 0 &&
|
||||
selectedWorkflows.length > 0 ? (
|
||||
<EditWorkflow
|
||||
globalUrl={globalUrl}
|
||||
inputworkflows={selectedWorkflows}
|
||||
inputname={webhookData.info.name}
|
||||
inputtype={webhookData.type}
|
||||
/>
|
||||
) : null;
|
||||
const workflowdata = Object.getOwnPropertyNames(webhookData).length > 0 && selectedWorkflows.length > 0 ?
|
||||
<EditWorkflow globalUrl={globalUrl} inputworkflows={selectedWorkflows} inputname={webhookData.info.name} inputtype={webhookData.type} /> : null
|
||||
|
||||
const loadedCheck = isLoaded ? (
|
||||
<div style={{ display: "flex", backgroundColor: "#f7f7f7" }}>
|
||||
<div style={{ flex: 1 }}>{workflowdata}</div>
|
||||
<div style={{ flex: 1 }}>{headerInfo}</div>
|
||||
const loadedCheck = isLoaded ?
|
||||
<div style={{display: "flex", backgroundColor: "#f7f7f7"}}>
|
||||
<div style={{"flex": 1}}>
|
||||
{workflowdata}
|
||||
</div>
|
||||
<div style={{"flex": 1}}>
|
||||
{headerInfo}
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
);
|
||||
|
||||
// FIXME: Use this for testing
|
||||
// <EditWorkflow globalUrl={globalUrl} inputname={"Helo?"} inputtype={"webhook"} /> : null
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return (
|
||||
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditWebhook;
|
||||
|
||||
+160
-173
File diff suppressed because one or more lines are too long
@@ -1,84 +1,84 @@
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
import React, { useState } from "react";
|
||||
import React, {useState} from 'react';
|
||||
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
|
||||
const bodyDivStyle = {
|
||||
margin: "auto",
|
||||
marginTop: "100px",
|
||||
width: "500px",
|
||||
};
|
||||
}
|
||||
|
||||
const ForgotPassword = (props) => {
|
||||
|
||||
const ForgotPassword = props => {
|
||||
const { globalUrl, isLoaded, isLoggedIn, surfaceColor, inputColor } = props;
|
||||
|
||||
|
||||
const boxStyle = {
|
||||
paddingLeft: "30px",
|
||||
paddingRight: "30px",
|
||||
paddingBottom: "30px",
|
||||
paddingTop: "30px",
|
||||
backgroundColor: surfaceColor,
|
||||
};
|
||||
}
|
||||
|
||||
const [username, setUsername] = useState("");
|
||||
const [resetInfo, setResetInfo] = useState(
|
||||
"You will receive an email with instructions shortly."
|
||||
);
|
||||
const [username, setUsername] = useState("")
|
||||
const [resetInfo, setResetInfo] = useState("You will receive an email with instructions shortly.")
|
||||
|
||||
const handleValidateForm = () => {
|
||||
return username.length > 3;
|
||||
};
|
||||
return username.length > 3
|
||||
}
|
||||
|
||||
if (isLoggedIn === true) {
|
||||
window.location.pathname = "/";
|
||||
window.location.pathname = "/"
|
||||
}
|
||||
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
// FIXME - add some check here ROFL
|
||||
|
||||
// Just use this one?
|
||||
var data = { username: username };
|
||||
var baseurl = globalUrl;
|
||||
var url = baseurl + "/api/v1/passwordresetmail";
|
||||
var data = {"username": username}
|
||||
var baseurl = globalUrl
|
||||
var url = baseurl+'/api/v1/passwordresetmail';
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
if (responseJson["success"] === false) {
|
||||
setResetInfo(responseJson["reason"]);
|
||||
setResetInfo(responseJson["reason"])
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setResetInfo("Error in userdata: " + error);
|
||||
.catch(error => {
|
||||
setResetInfo("Error in userdata: " + error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const onChangeUser = (e) => {
|
||||
setUsername(e.target.value);
|
||||
};
|
||||
setUsername(e.target.value)
|
||||
}
|
||||
|
||||
const data = (
|
||||
const data =
|
||||
<div style={bodyDivStyle}>
|
||||
<Paper style={boxStyle}>
|
||||
<form onSubmit={onSubmit} style={{ margin: "15px 15px 15px 15px" }}>
|
||||
<form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px"}}>
|
||||
<h2>Password reset</h2>
|
||||
<div>
|
||||
<TextField
|
||||
required
|
||||
fullWidth={true}
|
||||
color="primary"
|
||||
style={{ backgroundColor: inputColor }}
|
||||
style={{backgroundColor: inputColor}}
|
||||
InputProps={{
|
||||
style: {
|
||||
style:{
|
||||
height: "50px",
|
||||
color: "white",
|
||||
fontSize: "1em",
|
||||
@@ -93,26 +93,30 @@ const ForgotPassword = (props) => {
|
||||
onChange={onChangeUser}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: "flex", marginTop: "15px" }}>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
type="submit"
|
||||
style={{ flex: "1", marginRight: "5px" }}
|
||||
disabled={!handleValidateForm()}
|
||||
>
|
||||
SUBMIT
|
||||
</Button>
|
||||
<div style={{display: "flex", marginTop: "15px"}}>
|
||||
<Button color="primary" variant="contained" type="submit" style={{flex: "1", marginRight: "5px"}} disabled={!handleValidateForm()}>SUBMIT</Button>
|
||||
|
||||
</div>
|
||||
<div style={{marginTop: "20px"}}>
|
||||
{resetInfo}
|
||||
</div>
|
||||
<div style={{ marginTop: "20px" }}>{resetInfo}</div>
|
||||
</form>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
|
||||
const loadedCheck = isLoaded ? <div>{data}</div> : <div></div>;
|
||||
const loadedCheck = isLoaded ?
|
||||
<div>
|
||||
{data}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ForgotPassword;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, {useState, useEffect} from 'react';
|
||||
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
|
||||
const bodyDivStyle = {
|
||||
margin: "auto",
|
||||
textAlign: "center",
|
||||
width: "768px",
|
||||
};
|
||||
}
|
||||
|
||||
const boxStyle = {
|
||||
flex: "1",
|
||||
@@ -21,8 +21,8 @@ const boxStyle = {
|
||||
paddingTop: "30px",
|
||||
backgroundColor: "#e8eaf6",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
};
|
||||
flexDirection: "column"
|
||||
}
|
||||
|
||||
//const tmpdata = {
|
||||
// "username": "frikky",
|
||||
@@ -38,54 +38,51 @@ const boxStyle = {
|
||||
// FIXME - remove tmpdata
|
||||
// FIXME: Use isLoggedIn :)
|
||||
const Settings = (props) => {
|
||||
const { globalUrl, isLoaded } = props;
|
||||
const { globalUrl, isLoaded, } = props;
|
||||
|
||||
const [newPassword, setNewPassword] = useState("");
|
||||
const [newPassword2, setNewPassword2] = useState("");
|
||||
const [passwordFormMessage, setPasswordFormMessage] = useState("");
|
||||
|
||||
const onPasswordChange = () => {
|
||||
const data = {
|
||||
newpassword: newPassword,
|
||||
newpassword2: newPassword2,
|
||||
reference: props.match.params.key,
|
||||
};
|
||||
const url = globalUrl + "/api/v1/passwordreset";
|
||||
const data = {"newpassword": newPassword, "newpassword2": newPassword2, "reference": props.match.params.key}
|
||||
const url = globalUrl+'/api/v1/passwordreset';
|
||||
fetch(url, {
|
||||
mode: "cors",
|
||||
method: "POST",
|
||||
mode: 'cors',
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
credentials: "include",
|
||||
credentials: 'include',
|
||||
crossDomain: true,
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
if (responseJson["success"] === false) {
|
||||
setPasswordFormMessage(responseJson["reason"]);
|
||||
setPasswordFormMessage(responseJson["reason"])
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setPasswordFormMessage("Something went wrong.");
|
||||
.catch(error => {
|
||||
setPasswordFormMessage("Something went wrong.")
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// This should "always" have data
|
||||
useEffect(() => {});
|
||||
useEffect(() => {
|
||||
})
|
||||
|
||||
// Random names for type & autoComplete. Didn't research :^)
|
||||
const landingpageData = (
|
||||
<div style={{ display: "flex", marginTop: "80px" }}>
|
||||
const landingpageData =
|
||||
<div style={{display: "flex", marginTop: "80px"}}>
|
||||
<Paper style={boxStyle}>
|
||||
<h2>Password Reset</h2>
|
||||
<div style={{ flex: "1", display: "flex", flexDirection: "column" }}>
|
||||
<div style={{flex: "1", display: "flex", flexDirection: "column"}}>
|
||||
<TextField
|
||||
required
|
||||
style={{ flex: "1" }}
|
||||
style={{flex: "1"}}
|
||||
fullWidth={true}
|
||||
placeholder="New password"
|
||||
type="password"
|
||||
@@ -93,27 +90,23 @@ const Settings = (props) => {
|
||||
autoComplete="password"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
onChange={e => setNewPassword(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
required
|
||||
style={{ flex: "1" }}
|
||||
style={{flex: "1"}}
|
||||
fullWidth={true}
|
||||
type="password"
|
||||
placeholder="Repeat new password"
|
||||
id="standard-required"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(e) => setNewPassword2(e.target.value)}
|
||||
onChange={e => setNewPassword2(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
disabled={
|
||||
newPassword.length < 10 ||
|
||||
newPassword2.length < 10 ||
|
||||
newPassword !== newPassword2
|
||||
}
|
||||
style={{ width: "100%", height: "60px", marginTop: "10px" }}
|
||||
disabled={(newPassword.length < 10 || newPassword2.length < 10) || newPassword !== newPassword2}
|
||||
style={{width: "100%", height: "60px", marginTop: "10px"}}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => onPasswordChange()}
|
||||
@@ -123,14 +116,19 @@ const Settings = (props) => {
|
||||
<h3>{passwordFormMessage}</h3>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
|
||||
const loadedCheck = isLoaded ? (
|
||||
<div style={bodyDivStyle}>{landingpageData}</div>
|
||||
) : (
|
||||
<div></div>
|
||||
);
|
||||
const loadedCheck = isLoaded ?
|
||||
<div style={bodyDivStyle}>
|
||||
{landingpageData}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return(
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Settings;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
const HandlePayment = () => {
|
||||
return null;
|
||||
};
|
||||
return (
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
export default HandlePayment;
|
||||
export default HandlePayment
|
||||
|
||||
@@ -1,101 +1,100 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTheme } from "@material-ui/core/styles";
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTheme } from '@material-ui/core/styles';
|
||||
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import CardActionArea from "@material-ui/core/CardActionArea";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import CardHeader from "@material-ui/core/CardHeader";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActionArea from '@material-ui/core/CardActionArea';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
import CardHeader from '@material-ui/core/CardHeader';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
const Workflows = (props) => {
|
||||
const { globalUrl, isLoggedIn, isLoaded } = props;
|
||||
const { globalUrl, isLoggedIn, isLoaded, } = props
|
||||
const theme = useTheme();
|
||||
const [curView, setCurView] = useState(0);
|
||||
const [firstrequest, setFirstrequest] = useState(true);
|
||||
const [selectedItems, setSelectedItems] = useState([]);
|
||||
const [firstrequest, setFirstrequest] = useState(true)
|
||||
const [selectedItems, setSelectedItems] = useState([])
|
||||
|
||||
const viewdata1 = [
|
||||
{
|
||||
title: "General",
|
||||
content: "Learn about our ticketing solutions",
|
||||
subitems: [
|
||||
"title": "General",
|
||||
"content": "Learn about our ticketing solutions",
|
||||
"subitems": [
|
||||
{
|
||||
name: "Search",
|
||||
subtitle: "Search for anything, anywhere",
|
||||
"name": "Search",
|
||||
"subtitle": "Search for anything, anywhere",
|
||||
},
|
||||
{
|
||||
name: "Message",
|
||||
subtitle: "Read and send messages",
|
||||
"name": "Message",
|
||||
"subtitle": "Read and send messages",
|
||||
},
|
||||
{
|
||||
name: "Parse emails",
|
||||
subtitle: "what",
|
||||
"name": "Parse emails",
|
||||
"subtitle": "what",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Ticketing",
|
||||
subitems: [
|
||||
"title": "Ticketing",
|
||||
"subitems": [
|
||||
{
|
||||
name: "Search",
|
||||
subtitle: "Search for anything, anywhere",
|
||||
"name": "Search",
|
||||
"subtitle": "Search for anything, anywhere",
|
||||
},
|
||||
{
|
||||
name: "Message",
|
||||
subtitle: "Read and send messages",
|
||||
"name": "Message",
|
||||
"subtitle": "Read and send messages",
|
||||
},
|
||||
{
|
||||
name: "Parse emails",
|
||||
subtitle: "what",
|
||||
"name": "Parse emails",
|
||||
"subtitle": "what",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Threat intel",
|
||||
subitems: [
|
||||
"title": "Threat intel",
|
||||
"subitems": [
|
||||
{
|
||||
name: "Search",
|
||||
subtitle: "Search for anything, anywhere",
|
||||
"name": "Search",
|
||||
"subtitle": "Search for anything, anywhere",
|
||||
},
|
||||
{
|
||||
name: "Message",
|
||||
subtitle: "Read and send messages",
|
||||
"name": "Message",
|
||||
"subtitle": "Read and send messages",
|
||||
},
|
||||
{
|
||||
name: "Parse emails",
|
||||
subtitle: "what",
|
||||
"name": "Parse emails",
|
||||
"subtitle": "what",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
if (firstrequest) {
|
||||
setFirstrequest(false);
|
||||
setFirstrequest(false)
|
||||
if (props.match.params.key) {
|
||||
console.log("PROPS: ", props.match.params.key);
|
||||
const viewitem = viewdata1.find(
|
||||
(item) =>
|
||||
item.title.toLowerCase() === props.match.params.key.toLowerCase()
|
||||
);
|
||||
console.log("PROPS: ", props.match.params.key)
|
||||
const viewitem = viewdata1.find(item => item.title.toLowerCase() === props.match.params.key.toLowerCase())
|
||||
if (viewitem !== undefined && viewitem !== null) {
|
||||
setCurView(1);
|
||||
setCurView(1)
|
||||
//setSelectedItem(viewitem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const cardContentStyle = {
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
padding: 40,
|
||||
};
|
||||
}
|
||||
|
||||
const outerGridView = {
|
||||
width: "100%",
|
||||
marginTop: 15,
|
||||
};
|
||||
}
|
||||
|
||||
const paperStyle = {
|
||||
height: 300,
|
||||
@@ -105,61 +104,60 @@ const Workflows = (props) => {
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
textAlign: "center",
|
||||
};
|
||||
}
|
||||
|
||||
const HandleSelection = (data) => {
|
||||
const [selected, setSelected] = useState(false);
|
||||
|
||||
var baseStyle = JSON.parse(JSON.stringify(paperStyle));
|
||||
var baseStyle = JSON.parse(JSON.stringify(paperStyle))
|
||||
if (selected) {
|
||||
baseStyle.backgroundColor = "white";
|
||||
baseStyle.color = "black";
|
||||
baseStyle.backgroundColor = "white"
|
||||
baseStyle.color = "black"
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid
|
||||
item
|
||||
xs={4}
|
||||
onClick={() => {
|
||||
console.log(selectedItems);
|
||||
<Grid item xs={4} onClick={() => {
|
||||
console.log(selectedItems)
|
||||
if (selected) {
|
||||
const index = selectedItems.findIndex(
|
||||
(item) => item.title === data.title
|
||||
);
|
||||
const index = selectedItems.findIndex(item => item.title === data.title)
|
||||
if (index >= 0) {
|
||||
selectedItems.splice(index, 1);
|
||||
setSelectedItems(selectedItems);
|
||||
selectedItems.splice(index, 1)
|
||||
setSelectedItems(selectedItems)
|
||||
}
|
||||
} else {
|
||||
selectedItems.push(data);
|
||||
setSelectedItems(selectedItems);
|
||||
selectedItems.push(data)
|
||||
setSelectedItems(selectedItems)
|
||||
}
|
||||
|
||||
setSelected(!selected);
|
||||
setSelected(!selected)
|
||||
|
||||
//setCurView(1)
|
||||
//setSelectedItem(data)
|
||||
//window.location.pathname += "/"+data.title.toLowerCase()
|
||||
}}
|
||||
>
|
||||
}}>
|
||||
<Card style={baseStyle}>
|
||||
<CardActionArea style={cardContentStyle}>
|
||||
<CardContent>
|
||||
<Typography variant="h4">{data.title}</Typography>
|
||||
<Typography variant="h4">
|
||||
{data.title}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const view1 =
|
||||
curView === 0 ? (
|
||||
const view1 = curView === 0 ?
|
||||
<div>
|
||||
<Typography variant="h4">What are you interested in?</Typography>
|
||||
<Typography variant="h4">
|
||||
What are you interested in?
|
||||
</Typography>
|
||||
<Grid container style={outerGridView} spacing={3}>
|
||||
{viewdata1.map((data) => {
|
||||
return HandleSelection(data);
|
||||
{viewdata1.map(data => {
|
||||
return (
|
||||
HandleSelection(data)
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
{/*
|
||||
@@ -170,12 +168,13 @@ const Workflows = (props) => {
|
||||
</Button>
|
||||
*/}
|
||||
</div>
|
||||
) : null;
|
||||
: null
|
||||
|
||||
const view2 =
|
||||
curView === 1 ? (
|
||||
const view2 = curView === 1 ?
|
||||
<div>
|
||||
<Typography variant="h4">Step 2.</Typography>
|
||||
<Typography variant="h4">
|
||||
Step 2.
|
||||
</Typography>
|
||||
{/*
|
||||
<Grid container style={outerGridView} spacing={3}>
|
||||
{selectedItem.subitems === undefined ? null :
|
||||
@@ -200,16 +199,19 @@ const Workflows = (props) => {
|
||||
</Grid>
|
||||
*/}
|
||||
</div>
|
||||
) : null;
|
||||
: null
|
||||
|
||||
const baseView = (
|
||||
<div style={{ maxWidth: 1024, margin: "auto", paddingTop: 50 }}>
|
||||
const baseView =
|
||||
<div style={{maxWidth: 1024, margin: "auto", paddingTop: 50,}}>
|
||||
{view1}
|
||||
{view2}
|
||||
</div>
|
||||
);
|
||||
|
||||
return <div>{baseView}</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
{baseView}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Workflows;
|
||||
export default Workflows
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import React from "react";
|
||||
import React, {} from 'react';
|
||||
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Divider from "@material-ui/core/Divider";
|
||||
import { BrowserView, MobileView } from "react-device-detect";
|
||||
import ScheduleIcon from "@material-ui/icons/Schedule";
|
||||
import Web from "@material-ui/icons/Web";
|
||||
import AccountTree from "@material-ui/icons/AccountTree";
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
import {BrowserView, MobileView} from "react-device-detect";
|
||||
import ScheduleIcon from '@material-ui/icons/Schedule';
|
||||
import Web from '@material-ui/icons/Web';
|
||||
import AccountTree from '@material-ui/icons/AccountTree';
|
||||
|
||||
const bodyDivStyle = {
|
||||
margin: "auto",
|
||||
marginTop: "75px",
|
||||
textAlign: "center",
|
||||
width: "1100px",
|
||||
};
|
||||
}
|
||||
|
||||
const surfaceColor = "#27292D";
|
||||
const surfaceColor = "#27292D"
|
||||
const boxStyle = {
|
||||
flex: "1",
|
||||
marginLeft: "10px",
|
||||
@@ -26,93 +26,67 @@ const boxStyle = {
|
||||
textAlign: "center",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
};
|
||||
}
|
||||
|
||||
const bodyTextStyle = {
|
||||
color: "#ffffff",
|
||||
};
|
||||
}
|
||||
|
||||
const hrefStyle = {
|
||||
color: "black",
|
||||
textDecoration: "none",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Should be different if logged in :|
|
||||
const LandingPage = (props) => {
|
||||
const { isLoaded } = props;
|
||||
const { isLoaded} = props;
|
||||
|
||||
const textColor = "#8899A6";
|
||||
const iconColor = "#1DA1F2";
|
||||
const iconSize = "8em";
|
||||
const textColor = "#8899A6"
|
||||
const iconColor = "#1DA1F2"
|
||||
const iconSize = "8em"
|
||||
const GridLayout = (header, description, link, icon) => {
|
||||
return (
|
||||
<Paper style={boxStyle}>
|
||||
<a href={link} style={hrefStyle}>
|
||||
<div style={{ flex: "1", color: "#FFFFFF" }}>
|
||||
<div style={{flex: "1", color: "#FFFFFF"}}>
|
||||
<h2>{header}</h2>
|
||||
</div>
|
||||
<Divider />
|
||||
<div
|
||||
style={{
|
||||
flex: "3",
|
||||
marginLeft: "10px",
|
||||
marginRight: "10px",
|
||||
marginTop: "10px",
|
||||
color: textColor,
|
||||
}}
|
||||
>
|
||||
<div style={{flex: "3", marginLeft: "10px", marginRight: "10px", marginTop: "10px", color: textColor}}>
|
||||
{description}
|
||||
</div>
|
||||
<div style={{ margin: "auto" }}>{icon}</div>
|
||||
<Divider style={{ marginTop: "20px", marginBottom: "20px" }} />
|
||||
<div style={{ flex: "1", color: "#f85a3e" }}>
|
||||
<div style={{}}>Learn more</div>
|
||||
<div style={{margin: "auto"}}>
|
||||
{icon}
|
||||
</div>
|
||||
<Divider style={{marginTop: "20px", marginBottom: "20px"}} />
|
||||
<div style={{flex: "1", color: "#f85a3e"}}>
|
||||
<div style={{}} >
|
||||
Learn more
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const listitems = [
|
||||
GridLayout(
|
||||
"Simple integrations",
|
||||
"Easily use others' or create your own integration",
|
||||
"/docs/apps",
|
||||
<Web
|
||||
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
|
||||
/>
|
||||
),
|
||||
GridLayout(
|
||||
"Workflows",
|
||||
"Access the power of automation within minutes, whether its on premise or in the cloud",
|
||||
"/docs/workflows",
|
||||
<AccountTree
|
||||
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
|
||||
/>
|
||||
),
|
||||
GridLayout(
|
||||
"Realtime actions",
|
||||
"Beat the clock by leveraging our realtime triggers",
|
||||
"/docs/triggers",
|
||||
<ScheduleIcon
|
||||
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
|
||||
/>
|
||||
),
|
||||
];
|
||||
GridLayout("Simple integrations", "Easily use others' or create your own integration", "/docs/apps", <Web style={{fontSize: iconSize, marginTop: "20px", color: iconColor}} />),
|
||||
GridLayout("Workflows", "Access the power of automation within minutes, whether its on premise or in the cloud", "/docs/workflows", <AccountTree style={{fontSize: iconSize, marginTop: "20px", color: iconColor}} />),
|
||||
GridLayout("Realtime actions", "Beat the clock by leveraging our realtime triggers", "/docs/triggers", <ScheduleIcon style={{fontSize: iconSize, marginTop: "20px", color: iconColor}} />),
|
||||
]
|
||||
|
||||
// The actual landing page
|
||||
// <img style={{width: "400px"}} alt={"logo"} src={Default}/>
|
||||
const landingpageDataBrowser = (
|
||||
const landingpageDataBrowser =
|
||||
<div>
|
||||
<div style={bodyTextStyle}>
|
||||
<h1>Shuffle</h1>
|
||||
<h3 style={{ color: "#8899A6" }}>
|
||||
A general automation solution for Infosec and IT Professionals
|
||||
</h3>
|
||||
<h3 style={{color: "#8899A6"}}>A general automation solution for Infosec and IT Professionals</h3>
|
||||
</div>
|
||||
<a href="/register" style={hrefStyle}>
|
||||
<Button
|
||||
style={{ width: "180px", height: "50px", borderRadius: "0px" }}
|
||||
style={{width: "180px", height: "50px", borderRadius: "0px"}}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
>
|
||||
@@ -121,36 +95,32 @@ const LandingPage = (props) => {
|
||||
</a>
|
||||
<a href="/contact" style={hrefStyle}>
|
||||
<Button
|
||||
style={{ width: "180px", height: "50px", borderRadius: "0px" }}
|
||||
style={{width: "180px", height: "50px", borderRadius: "0px"}}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
Contact
|
||||
</Button>
|
||||
</a>
|
||||
<div style={{ display: "flex", marginTop: "100px" }}>
|
||||
{listitems.map((item) => {
|
||||
return <div>{item}</div>;
|
||||
<div style={{display: "flex", marginTop: "100px"}}>
|
||||
{listitems.map(item => {
|
||||
return (
|
||||
<div>
|
||||
{item}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const landingpageDataMobile = (
|
||||
const landingpageDataMobile =
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
marginLeft: "10px",
|
||||
marginRight: "10px",
|
||||
}}
|
||||
>
|
||||
<div style={{color: "white", textAlign: "center", marginLeft: "10px", marginRight: "10px"}}>
|
||||
<h1>Shuffle</h1>
|
||||
<h3>A general automation solution for Infosec and IT Professionals</h3>
|
||||
<a href="/contact" style={hrefStyle}>
|
||||
<Button
|
||||
style={{ width: "220px", height: "60px", borderRadius: "0px" }}
|
||||
style={{width: "220px", height: "60px", borderRadius: "0px"}}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
@@ -158,24 +128,20 @@ const LandingPage = (props) => {
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
style={{ display: "flex", flexDirection: "column", marginTop: "100px" }}
|
||||
>
|
||||
<div>{listitems[0]}</div>
|
||||
<div style={{ marginTop: "20px" }}>{listitems[1]}</div>
|
||||
<div style={{ marginTop: "20px", marginBottom: "30px" }}>
|
||||
<div style={{display: "flex", flexDirection: "column", marginTop: "100px"}}>
|
||||
<div>
|
||||
{listitems[0]}
|
||||
</div>
|
||||
<div style={{marginTop: "20px"}}>
|
||||
{listitems[1]}
|
||||
</div>
|
||||
<div style={{marginTop: "20px", marginBottom: "30px"}}>
|
||||
{listitems[2]}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
marginTop: "20px",
|
||||
marginBottom: "30px",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
<div style={{marginTop: "20px", marginBottom: "30px", textAlign: "center"}}>
|
||||
<a href="/contact" style={hrefStyle}>
|
||||
<Button
|
||||
style={{ width: "220px", height: "60px", borderRadius: "0px" }}
|
||||
style={{width: "220px", height: "60px", borderRadius: "0px"}}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
@@ -185,21 +151,29 @@ const LandingPage = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
// Reroute if the user is logged in
|
||||
// const landingSite = isLoggedIn ? <Workflows globalUrl={globalUrl}{...props} /> : <div style={bodyDivStyle}>{landingpageData}</div>
|
||||
const landingSite = <div style={bodyDivStyle}>{landingpageDataBrowser}</div>;
|
||||
const landingSite = <div style={bodyDivStyle}>{landingpageDataBrowser}</div>
|
||||
|
||||
const loadedCheck = isLoaded ? (
|
||||
const loadedCheck = isLoaded ?
|
||||
<div>
|
||||
<BrowserView>
|
||||
{landingSite}
|
||||
</BrowserView>
|
||||
<MobileView>
|
||||
{landingpageDataMobile}
|
||||
</MobileView>
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
<BrowserView>{landingSite}</BrowserView>
|
||||
<MobileView>{landingpageDataMobile}</MobileView>
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
);
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return(
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default LandingPage;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, {} from 'react';
|
||||
|
||||
const bodyDivStyle = {
|
||||
transform: "translate(-50%, -50%)",
|
||||
@@ -7,10 +7,15 @@ const bodyDivStyle = {
|
||||
position: "absolute",
|
||||
width: "500px",
|
||||
color: "white",
|
||||
};
|
||||
}
|
||||
|
||||
// Should be different if logged in :|
|
||||
const LandingPageLoggedin = (props) => {
|
||||
return <div style={bodyDivStyle}>TMP landingpage when logged in</div>;
|
||||
};
|
||||
|
||||
return(
|
||||
<div style={bodyDivStyle}>
|
||||
TMP landingpage when logged in
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default LandingPageLoggedin;
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import React, { useState } from "react";
|
||||
import React, {useState } from 'react';
|
||||
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import CardActionArea from "@material-ui/core/CardActionArea";
|
||||
import CardMedia from "@material-ui/core/CardMedia";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import CardActions from "@material-ui/core/CardActions";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Divider from "@material-ui/core/Divider";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import { BrowserView, MobileView } from "react-device-detect";
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActionArea from '@material-ui/core/CardActionArea';
|
||||
import CardMedia from '@material-ui/core/CardMedia';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import {BrowserView, MobileView} from "react-device-detect";
|
||||
|
||||
import ScheduleIcon from "@material-ui/icons/Schedule";
|
||||
import Web from "@material-ui/icons/Web";
|
||||
import AccountTree from "@material-ui/icons/AccountTree";
|
||||
import InfoIcon from "@material-ui/icons/Info";
|
||||
import ArrowForwardIcon from "@material-ui/icons/ArrowForward";
|
||||
import CreateIcon from "@material-ui/icons/Create";
|
||||
import ScheduleIcon from '@material-ui/icons/Schedule';
|
||||
import Web from '@material-ui/icons/Web';
|
||||
import AccountTree from '@material-ui/icons/AccountTree';
|
||||
import InfoIcon from '@material-ui/icons/Info';
|
||||
import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
|
||||
import CreateIcon from '@material-ui/icons/Create';
|
||||
|
||||
const bodyDivStyle = {
|
||||
margin: "auto",
|
||||
};
|
||||
}
|
||||
|
||||
const surfaceColor = "#27292D";
|
||||
const surfaceColor = "#27292D"
|
||||
const boxStyle = {
|
||||
flex: "1",
|
||||
marginLeft: "10px",
|
||||
@@ -33,333 +33,177 @@ const boxStyle = {
|
||||
textAlign: "center",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
};
|
||||
}
|
||||
|
||||
const bodyTextStyle = {
|
||||
color: "#ffffff",
|
||||
};
|
||||
}
|
||||
|
||||
const hrefStyle = {
|
||||
color: "inherit",
|
||||
textDecoration: "none",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Should be different if logged in :|
|
||||
const LandingPage = (props) => {
|
||||
const { isLoaded } = props;
|
||||
const { isLoaded} = props;
|
||||
|
||||
const textColor = "#8899A6";
|
||||
const iconColor = "#1DA1F2";
|
||||
const iconSize = "8em";
|
||||
const textColor = "#8899A6"
|
||||
const iconColor = "#1DA1F2"
|
||||
const iconSize = "8em"
|
||||
|
||||
const GridLayout = (header, description, link, icon) => {
|
||||
return (
|
||||
<Paper style={boxStyle}>
|
||||
<a href={link} style={hrefStyle}>
|
||||
<div style={{ flex: "1", color: "#FFFFFF" }}>
|
||||
<div style={{flex: "1", color: "#FFFFFF"}}>
|
||||
<h2>{header}</h2>
|
||||
</div>
|
||||
<Divider />
|
||||
<div
|
||||
style={{
|
||||
flex: "3",
|
||||
marginLeft: "10px",
|
||||
marginRight: "10px",
|
||||
marginTop: "10px",
|
||||
color: textColor,
|
||||
}}
|
||||
>
|
||||
<div style={{flex: "3", marginLeft: "10px", marginRight: "10px", marginTop: "10px", color: textColor}}>
|
||||
{description}
|
||||
</div>
|
||||
<div style={{ margin: "auto" }}>{icon}</div>
|
||||
<Divider style={{ marginTop: "20px", marginBottom: "20px" }} />
|
||||
<div style={{ flex: "1", color: "#f85a3e" }}>
|
||||
<div style={{}}>Learn more</div>
|
||||
<div style={{margin: "auto"}}>
|
||||
{icon}
|
||||
</div>
|
||||
<Divider style={{marginTop: "20px", marginBottom: "20px"}} />
|
||||
<div style={{flex: "1", color: "#f85a3e"}}>
|
||||
<div style={{}} >
|
||||
Learn more
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const listitems = [
|
||||
GridLayout(
|
||||
"Simple integrations",
|
||||
"Easily use others' or create your own integration",
|
||||
"/docs/features",
|
||||
<Web
|
||||
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
|
||||
/>
|
||||
),
|
||||
GridLayout(
|
||||
"Workflows",
|
||||
"Access the power of automation within minutes, whether its on premise or in the cloud",
|
||||
"/docs/features",
|
||||
<AccountTree
|
||||
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
|
||||
/>
|
||||
),
|
||||
GridLayout(
|
||||
"Realtime actions",
|
||||
"Beat the clock by leveraging our realtime triggers",
|
||||
"/docs/features",
|
||||
<ScheduleIcon
|
||||
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
|
||||
/>
|
||||
),
|
||||
];
|
||||
GridLayout("Simple integrations", "Easily use others' or create your own integration", "/docs/features", <Web style={{fontSize: iconSize, marginTop: "20px", color: iconColor}} />),
|
||||
GridLayout("Workflows", "Access the power of automation within minutes, whether its on premise or in the cloud", "/docs/features", <AccountTree style={{fontSize: iconSize, marginTop: "20px", color: iconColor}} />),
|
||||
GridLayout("Realtime actions", "Beat the clock by leveraging our realtime triggers", "/docs/features", <ScheduleIcon style={{fontSize: iconSize, marginTop: "20px", color: iconColor}} />),
|
||||
]
|
||||
|
||||
// The actual landing page
|
||||
// <img style={{width: "400px"}} alt={"logo"} src={Default}/>
|
||||
//We start by understanding your unique environment to help identify the right thing to automate.
|
||||
const secondaryColor = "rgba(167,46,87,1)";
|
||||
const primaryColor = "rgba(25, 35, 94, 1)";
|
||||
const secondaryColor = "rgba(167,46,87,1)"
|
||||
const primaryColor = "rgba(25, 35, 94, 1)"
|
||||
|
||||
const paperStyle = {
|
||||
flex: 1,
|
||||
backgroundColor: "inherit",
|
||||
cursor: "pointer",
|
||||
};
|
||||
}
|
||||
|
||||
const secondaryItemList = [
|
||||
{
|
||||
primaryText: "No time to waste",
|
||||
secondaryText:
|
||||
"Bring all your applications into a single view, and make them all work together flawlessly!",
|
||||
secondaryText: "Bring all your applications into a single view, and make them all work together flawlessly!",
|
||||
image: "/images/time.jpg",
|
||||
},
|
||||
{
|
||||
}, {
|
||||
primaryText: "Get a better overview",
|
||||
secondaryText:
|
||||
"Don't know what's happening? We'll help you track and act on your most valuable KPI's!",
|
||||
secondaryText: "Don't know what's happening? We'll help you track and act on your most valuable KPI's!",
|
||||
image: "/images/overview.jpg",
|
||||
},
|
||||
{
|
||||
}, {
|
||||
primaryText: "Conquer your tasks",
|
||||
secondaryText:
|
||||
"Get access to powerful tools and pre-made workflows to help you crush your teams daily tasks!",
|
||||
secondaryText: "Get access to powerful tools and pre-made workflows to help you crush your teams daily tasks!",
|
||||
image: "/images/burnout.jpg",
|
||||
},
|
||||
];
|
||||
]
|
||||
const [image, setImage] = useState(secondaryItemList[0].image);
|
||||
|
||||
const landingpageDataBrowser = (
|
||||
const landingpageDataBrowser =
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
backgroundImage: "url('/images/test.jpg')",
|
||||
backgroundSize: "80% 100%",
|
||||
backgroundRepeat: "no-repeat",
|
||||
minHeight: "100vh",
|
||||
maxHeight: 1024,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
textAlign: "left",
|
||||
paddingTop: 135,
|
||||
maxWidth: 700,
|
||||
paddingLeft: "50%",
|
||||
color: secondaryColor,
|
||||
display: "flex",
|
||||
fontSize: 25,
|
||||
}}
|
||||
>
|
||||
<div style={{ flex: 1 }}>
|
||||
<div style={{backgroundImage: "url('/images/test.jpg')", backgroundSize: "80% 100%", backgroundRepeat: "no-repeat", minHeight: "100vh", maxHeight: 1024}}>
|
||||
<div style={{textAlign: "left", paddingTop: 135, maxWidth: 700, paddingLeft: "50%", color: secondaryColor, display: "flex", fontSize: 25}}>
|
||||
<div style={{flex: 1}}>
|
||||
<a href="/docs/about" style={hrefStyle}>
|
||||
<Grid container direction="row" alignItems="center">
|
||||
<Grid item>
|
||||
<InfoIcon />
|
||||
</Grid>
|
||||
<Grid item style={{ marginLeft: 5 }}>
|
||||
<Grid item style={{marginLeft: 5}}>
|
||||
About
|
||||
</Grid>
|
||||
</Grid>
|
||||
</a>
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<div style={{flex: 1}}>
|
||||
<a href="/contact" style={hrefStyle}>
|
||||
<Grid container direction="row" alignItems="center">
|
||||
<Grid item>
|
||||
<CreateIcon />
|
||||
</Grid>
|
||||
<Grid item style={{ marginLeft: 5 }}>
|
||||
<Grid item style={{marginLeft: 5}}>
|
||||
Get in touch
|
||||
</Grid>
|
||||
</Grid>
|
||||
</a>
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<div style={{flex: 1}}>
|
||||
<a href="/login" style={hrefStyle}>
|
||||
<Button
|
||||
style={{
|
||||
borderRadius: 25,
|
||||
height: 50,
|
||||
minWidth: 200,
|
||||
backgroundColor: secondaryColor,
|
||||
color: "white",
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
style={{borderRadius: 25, height: 50, minWidth: 200, backgroundColor: secondaryColor, color: "white"}} variant="contained">
|
||||
Try it out <ArrowForwardIcon />
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
(bodyTextStyle,
|
||||
{
|
||||
textAlign: "left",
|
||||
paddingTop: "8%",
|
||||
paddingLeft: "28%",
|
||||
maxWidth: 430,
|
||||
})
|
||||
}
|
||||
>
|
||||
<div style={{ fontSize: 25, color: "rgba(0,0,0,0.45)" }}>Shuffle</div>
|
||||
<div style={{ fontSize: 50, color: "rgba(0,0,0,0.7)" }}>
|
||||
INFORMATION <div style={{ color: secondaryColor }}>OVERLOAD</div>
|
||||
<div style={bodyTextStyle, {textAlign: "left", paddingTop: "8%", paddingLeft: "28%", maxWidth: 430,}}>
|
||||
<div style={{fontSize: 25, color:"rgba(0,0,0,0.45)"}}>
|
||||
Shuffle
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 20,
|
||||
color: "rgba(0, 0, 0, 0.45)",
|
||||
marginTop: 20,
|
||||
}}
|
||||
>
|
||||
Everyone run into the same fundamental operational problems. Mailbox
|
||||
chaos, tickets getting out of hand and a constant feeling of being
|
||||
overwhelmed. The good news?{" "}
|
||||
<div style={{ color: secondaryColor, marginTop: 10 }}>
|
||||
Shuffle solves them.
|
||||
<div style={{fontSize: 50, color: "rgba(0,0,0,0.7)"}}>
|
||||
INFORMATION <div style={{color: secondaryColor}}>OVERLOAD</div>
|
||||
</div>
|
||||
<div style={{fontSize: 20, color: "rgba(0, 0, 0, 0.45)", marginTop: 20,}}>
|
||||
Everyone run into the same fundamental operational problems. Mailbox chaos, tickets getting out of hand and a constant feeling of being overwhelmed. The good news? <div style={{color: secondaryColor, marginTop: 10}}>Shuffle solves them.</div>
|
||||
</div>
|
||||
<a href="/docs/features" style={hrefStyle}>
|
||||
<Button
|
||||
style={{
|
||||
borderRadius: 25,
|
||||
height: 50,
|
||||
marginTop: 50,
|
||||
width: 200,
|
||||
backgroundColor: secondaryColor,
|
||||
color: "white",
|
||||
}}
|
||||
style={{borderRadius: 25, height: 50, marginTop: 50, width: 200, backgroundColor: secondaryColor, color: "white"}}
|
||||
variant="contained"
|
||||
>
|
||||
Learn how
|
||||
</Button>
|
||||
>Learn how</Button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
minHeight: 1024,
|
||||
width: "100%",
|
||||
backgroundImage: "linear-gradient(to bottom right, #19235e, #19235e)",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
minHeight: 1000,
|
||||
paddingTop: 150,
|
||||
maxWidth: 1250,
|
||||
margin: "auto",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "rgba(255,255,255,0.8",
|
||||
fontSize: 60,
|
||||
marginLeft: 25,
|
||||
}}
|
||||
>
|
||||
<div style={{minHeight: 1024, width: "100%", backgroundImage: "linear-gradient(to bottom right, #19235e, #19235e)",}}>
|
||||
<div style={{minHeight: 1000, paddingTop: 150, maxWidth: 1250, margin: "auto"}}>
|
||||
<div style={{color: "rgba(255,255,255,0.8", fontSize: 60, marginLeft: 25, }}>
|
||||
<b>Automation is just the beginning </b>
|
||||
</div>
|
||||
<div style={{ marginTop: 40, display: "flex", flexDirection: "row" }}>
|
||||
<div
|
||||
style={{
|
||||
flex: 8,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
fontSize: 40,
|
||||
}}
|
||||
>
|
||||
<div style={{marginTop: 40, display: 'flex', flexDirection: "row"}}>
|
||||
<div style={{flex: 8, display: "flex", flexDirection: "column", fontSize: 40, }}>
|
||||
{secondaryItemList.map((data, index) => {
|
||||
const color =
|
||||
image === data.image
|
||||
? "rgba(255,255,255,1)"
|
||||
: "rgba(255,255,255,0.4)";
|
||||
const color = image === data.image ? "rgba(255,255,255,1)" : "rgba(255,255,255,0.4)"
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
borderRadius: 15,
|
||||
padding: 25,
|
||||
maxWidth: 600,
|
||||
height: 150,
|
||||
fontSize: 40,
|
||||
color: color,
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => setImage(data.image)}
|
||||
>
|
||||
<div style={{borderRadius: 15, padding: 25, maxWidth: 600, height: 150, fontSize: 40, color: color, cursor: "pointer"}} onClick={() => setImage(data.image)}>
|
||||
{data.primaryText}
|
||||
<div style={{ fontSize: 22, marginTop: 10 }}>
|
||||
<div style={{fontSize: 22, marginTop: 10, }}>
|
||||
{data.secondaryText}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<div style={{ flex: 1 }} />
|
||||
<div style={{ flex: 10, height: "100%", width: "100%" }}>
|
||||
<img
|
||||
src={image}
|
||||
style={{
|
||||
borderRadius: 15,
|
||||
minHeight: "100%",
|
||||
minWidth: "100%",
|
||||
maxWidth: "100%",
|
||||
maxHeight: "100%",
|
||||
}}
|
||||
/>
|
||||
<div style={{flex: 1}} />
|
||||
<div style={{flex: 10, height: "100%", width: "100%",}}>
|
||||
<img src={image} style={{borderRadius: 15, minHeight: "100%", minWidth: "100%", maxWidth: "100%", maxHeight: "100%"}}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
maxWidth: 1250,
|
||||
paddingTop: 100,
|
||||
paddingBottom: 100,
|
||||
margin: "auto",
|
||||
color: "rgba(255,255,255,0.8)",
|
||||
}}
|
||||
>
|
||||
<Divider style={{ backgroundColor: "rgba(255,255,255,0.6)" }} />
|
||||
<div
|
||||
style={{
|
||||
marginTop: 100,
|
||||
fontSize: 40,
|
||||
display: "flex",
|
||||
marginLeft: 100,
|
||||
marginRight: 100,
|
||||
}}
|
||||
>
|
||||
<div style={{ flex: 3 }}>
|
||||
<div style={{maxWidth: 1250, paddingTop: 100, paddingBottom: 100, margin: "auto", color: "rgba(255,255,255,0.8)"}}>
|
||||
<Divider style={{backgroundColor: "rgba(255,255,255,0.6)"}} />
|
||||
<div style={{marginTop: 100, fontSize: 40, display: "flex", marginLeft: 100, marginRight: 100}}>
|
||||
<div style={{flex: 3}}>
|
||||
Learn more about the benefits of Shuffle
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<div style={{flex: 1}}>
|
||||
<a href="/docs/features" style={hrefStyle}>
|
||||
<Button
|
||||
fullWidth
|
||||
style={{
|
||||
borderRadius: 25,
|
||||
minHeight: 50,
|
||||
minWidth: 200,
|
||||
backgroundColor: secondaryColor,
|
||||
color: "white",
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
style={{borderRadius: 25, minHeight: 50, minWidth: 200, backgroundColor: secondaryColor, color: "white"}} variant="contained">
|
||||
See features
|
||||
</Button>
|
||||
</a>
|
||||
@@ -367,34 +211,20 @@ const LandingPage = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
textAlign: "center",
|
||||
maxWidth: 1100,
|
||||
minHeight: 600,
|
||||
paddingTop: 100,
|
||||
margin: "auto",
|
||||
color: "rgba(0,0,0,1)",
|
||||
}}
|
||||
>
|
||||
<div style={{ fontSize: 50 }}>
|
||||
<div style={{textAlign: "center", maxWidth: 1100, minHeight: 600, paddingTop: 100, margin: "auto", color: "rgba(0,0,0,1)"}}>
|
||||
<div style={{fontSize: 50}}>
|
||||
<b>Focus on the work that matters to you</b>
|
||||
</div>
|
||||
<div
|
||||
style={{ fontSize: 20, color: "rgba(0,0,0,0.7)", maxWidth: "100%" }}
|
||||
>
|
||||
Menial tasks, scattered content, constant copy pasting, waste of
|
||||
talent - <b>there's a smarter way to work.</b>
|
||||
<div style={{fontSize: 20, color: "rgba(0,0,0,0.7)", maxWidth: "100%"}}>
|
||||
Menial tasks, scattered content, constant copy pasting, waste of talent - <b>there's a smarter way to work.</b>
|
||||
</div>
|
||||
<div style={{ display: "flex", marginTop: 50 }}>
|
||||
<Card
|
||||
onClick={() => {
|
||||
window.location.pathname = "/docs/features";
|
||||
}}
|
||||
style={{ flex: 1, margin: 10, textAlign: "center" }}
|
||||
>
|
||||
<div style={{display: "flex", marginTop: 50}}>
|
||||
<Card onClick={() => {window.location.pathname = "/docs/features"}} style={{flex: 1, margin: 10, textAlign: "center"}}>
|
||||
<CardActionArea>
|
||||
<CardMedia title="TEST" image="/images/time.jpg" />
|
||||
<CardMedia
|
||||
title="TEST"
|
||||
image="/images/time.jpg"
|
||||
/>
|
||||
<CardContent>
|
||||
<h3>Premade playbooks</h3>
|
||||
<p>Get your automation done with minimal effort</p>
|
||||
@@ -404,14 +234,12 @@ const LandingPage = (props) => {
|
||||
Learn more
|
||||
</Button>
|
||||
</Card>
|
||||
<Card
|
||||
onClick={() => {
|
||||
window.location.pathname = "/docs/features";
|
||||
}}
|
||||
style={{ flex: 1, margin: 10, textAlign: "center" }}
|
||||
>
|
||||
<Card onClick={() => {window.location.pathname = "/docs/features"}} style={{flex: 1, margin: 10, textAlign: "center"}}>
|
||||
<CardActionArea>
|
||||
<CardMedia title="TEST" image="/images/time.jpg" />
|
||||
<CardMedia
|
||||
title="TEST"
|
||||
image="/images/time.jpg"
|
||||
/>
|
||||
<CardContent>
|
||||
<h3>Open frameworks</h3>
|
||||
<p>Mitre Att&ck, OpenAPI and more!</p>
|
||||
@@ -421,14 +249,12 @@ const LandingPage = (props) => {
|
||||
Learn more
|
||||
</Button>
|
||||
</Card>
|
||||
<Card
|
||||
onClick={() => {
|
||||
window.location.pathname = "/docs/features";
|
||||
}}
|
||||
style={{ flex: 1, margin: 10, textAlign: "center" }}
|
||||
>
|
||||
<Card onClick={() => {window.location.pathname = "/docs/features"}} style={{flex: 1, margin: 10, textAlign: "center"}}>
|
||||
<CardActionArea>
|
||||
<CardMedia title="TEST" image="/images/time.jpg" />
|
||||
<CardMedia
|
||||
title="TEST"
|
||||
image="/images/time.jpg"
|
||||
/>
|
||||
<CardContent>
|
||||
<h3>Hundreds of integrations</h3>
|
||||
<p>Quickly integrate your software applications</p>
|
||||
@@ -438,14 +264,12 @@ const LandingPage = (props) => {
|
||||
Learn more
|
||||
</Button>
|
||||
</Card>
|
||||
<Card
|
||||
style={{ flex: 1, margin: 10, textAlign: "center" }}
|
||||
onClick={() => {
|
||||
window.location.pathname = "/docs/features";
|
||||
}}
|
||||
>
|
||||
<Card style={{flex: 1, margin: 10, textAlign: "center"}} onClick={() => {window.location.pathname = "/docs/features"}}>
|
||||
<CardActionArea>
|
||||
<CardMedia title="TEST" image="images/time.jpg" />
|
||||
<CardMedia
|
||||
title="TEST"
|
||||
image="images/time.jpg"
|
||||
/>
|
||||
<CardContent>
|
||||
<h3>Automated compliance</h3>
|
||||
<p>Stuck with compliance needs you can't meet?</p>
|
||||
@@ -458,23 +282,15 @@ const LandingPage = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const landingpageDataMobile = (
|
||||
<div style={{ backgroundColor: "#1F2023", paddingTop: 30 }}>
|
||||
<div
|
||||
style={{
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
marginLeft: "10px",
|
||||
marginRight: "10px",
|
||||
}}
|
||||
>
|
||||
const landingpageDataMobile =
|
||||
<div style={{backgroundColor: "#1F2023", paddingTop: 30}}>
|
||||
<div style={{color: "white", textAlign: "center", marginLeft: "10px", marginRight: "10px"}}>
|
||||
<h1>Shuffle</h1>
|
||||
<h3>A general automation solution for Infosec and IT Professionals</h3>
|
||||
<a href="/contact" style={hrefStyle}>
|
||||
<Button
|
||||
style={{ width: "220px", height: "60px", borderRadius: "0px" }}
|
||||
style={{width: "220px", height: "60px", borderRadius: "0px"}}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
@@ -482,24 +298,20 @@ const LandingPage = (props) => {
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
style={{ display: "flex", flexDirection: "column", marginTop: "100px" }}
|
||||
>
|
||||
<div>{listitems[0]}</div>
|
||||
<div style={{ marginTop: "20px" }}>{listitems[1]}</div>
|
||||
<div style={{ marginTop: "20px", marginBottom: "30px" }}>
|
||||
<div style={{display: "flex", flexDirection: "column", marginTop: "100px"}}>
|
||||
<div>
|
||||
{listitems[0]}
|
||||
</div>
|
||||
<div style={{marginTop: "20px"}}>
|
||||
{listitems[1]}
|
||||
</div>
|
||||
<div style={{marginTop: "20px", marginBottom: "30px"}}>
|
||||
{listitems[2]}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
marginTop: "20px",
|
||||
marginBottom: "30px",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
<div style={{marginTop: "20px", marginBottom: "30px", textAlign: "center"}}>
|
||||
<a href="/contact" style={hrefStyle}>
|
||||
<Button
|
||||
style={{ width: "220px", height: "60px", borderRadius: "0px" }}
|
||||
style={{width: "220px", height: "60px", borderRadius: "0px"}}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
@@ -509,21 +321,29 @@ const LandingPage = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
// Reroute if the user is logged in
|
||||
// const landingSite = isLoggedIn ? <Workflows globalUrl={globalUrl}{...props} /> : <div style={bodyDivStyle}>{landingpageData}</div>
|
||||
const landingSite = <div style={bodyDivStyle}>{landingpageDataBrowser}</div>;
|
||||
const landingSite = <div style={bodyDivStyle}>{landingpageDataBrowser}</div>
|
||||
|
||||
const loadedCheck = isLoaded ? (
|
||||
const loadedCheck = isLoaded ?
|
||||
<div>
|
||||
<BrowserView>
|
||||
{landingSite}
|
||||
</BrowserView>
|
||||
<MobileView>
|
||||
{landingpageDataMobile}
|
||||
</MobileView>
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
<BrowserView>{landingSite}</BrowserView>
|
||||
<MobileView>{landingpageDataMobile}</MobileView>
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
);
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return(
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default LandingPage;
|
||||
|
||||
+153
-252
@@ -1,52 +1,40 @@
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
import React, { useState } from "react";
|
||||
import { makeStyles } from "@material-ui/styles";
|
||||
import { useInterval } from "react-powerhooks";
|
||||
import React, { useState } from 'react';
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import { useInterval } from 'react-powerhooks';
|
||||
|
||||
import {CircularProgress, TextField, Button, Paper, Typography} from '@material-ui/core'
|
||||
import { useTheme } from '@material-ui/core/styles';
|
||||
|
||||
import {
|
||||
CircularProgress,
|
||||
TextField,
|
||||
Button,
|
||||
Paper,
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { useTheme } from "@material-ui/core/styles";
|
||||
|
||||
const hrefStyle = {
|
||||
color: "white",
|
||||
textDecoration: "none",
|
||||
};
|
||||
textDecoration: "none"
|
||||
}
|
||||
|
||||
const bodyDivStyle = {
|
||||
margin: "auto",
|
||||
marginTop: 150,
|
||||
width: "500px",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const useStyles = makeStyles({
|
||||
notchedOutline: {
|
||||
borderColor: "#f85a3e !important",
|
||||
borderColor: "#f85a3e !important"
|
||||
},
|
||||
});
|
||||
|
||||
const LoginDialog = (props) => {
|
||||
const LoginDialog = props => {
|
||||
const theme = useTheme();
|
||||
|
||||
const {
|
||||
globalUrl,
|
||||
isLoaded,
|
||||
isLoggedIn,
|
||||
setIsLoggedIn,
|
||||
setCookie,
|
||||
register,
|
||||
checkLogin,
|
||||
} = props;
|
||||
const { globalUrl, isLoaded, isLoggedIn, setIsLoggedIn, setCookie, register, checkLogin } = props;
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [firstRequest, setFirstRequest] = useState(true);
|
||||
const [loginLoading, setLoginLoading] = useState(false);
|
||||
const [loginViewLoading, setLoginViewLoading] = useState(false);
|
||||
const [ssoUrl, setSSOUrl] = useState("");
|
||||
const [ssoUrl, setSSOUrl] = useState("")
|
||||
|
||||
const [MFAField, setMFAField] = useState(false);
|
||||
const [MFAValue, setMFAValue] = useState("");
|
||||
@@ -58,163 +46,151 @@ const LoginDialog = (props) => {
|
||||
const [loginInfo, setLoginInfo] = useState("");
|
||||
|
||||
const handleValidateForm = () => {
|
||||
return username.length > 1 && password.length > 1;
|
||||
};
|
||||
return (username.length > 1 && password.length > 1);
|
||||
}
|
||||
|
||||
if (isLoggedIn === true) {
|
||||
window.location.pathname = "/workflows";
|
||||
window.location.pathname = "/workflows"
|
||||
}
|
||||
|
||||
const checkAdmin = () => {
|
||||
const url = globalUrl + "/api/v1/checkusers";
|
||||
const url = globalUrl + '/api/v1/checkusers';
|
||||
fetch(url, {
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
if (responseJson["success"] === false) {
|
||||
setLoginInfo(responseJson["reason"]);
|
||||
setLoginInfo(responseJson["reason"])
|
||||
} else {
|
||||
if (
|
||||
responseJson.sso_url !== undefined &&
|
||||
responseJson.sso_url !== null
|
||||
) {
|
||||
setSSOUrl(responseJson.sso_url);
|
||||
if (responseJson.sso_url !== undefined && responseJson.sso_url !== null) {
|
||||
setSSOUrl(responseJson.sso_url)
|
||||
}
|
||||
|
||||
if (loginViewLoading) {
|
||||
setLoginViewLoading(false);
|
||||
checkLogin();
|
||||
stop();
|
||||
setLoginViewLoading(false)
|
||||
checkLogin()
|
||||
stop()
|
||||
|
||||
if (
|
||||
responseJson.reason !== undefined &&
|
||||
responseJson.reason !== null
|
||||
) {
|
||||
setLoginInfo(responseJson.reason);
|
||||
if (responseJson.reason !== undefined && responseJson.reason !== null) {
|
||||
setLoginInfo(responseJson.reason)
|
||||
}
|
||||
}
|
||||
|
||||
if (responseJson.reason === "stay") {
|
||||
window.location.pathname = "/adminsetup";
|
||||
window.location.pathname = "/adminsetup"
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
.catch(error => {
|
||||
if (!loginViewLoading) {
|
||||
setLoginViewLoading(true)
|
||||
start()
|
||||
}
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
if (!loginViewLoading) {
|
||||
setLoginViewLoading(true);
|
||||
start();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const { start, stop } = useInterval({
|
||||
duration: 3000,
|
||||
startImmediate: false,
|
||||
callback: () => {
|
||||
checkAdmin();
|
||||
},
|
||||
});
|
||||
checkAdmin()
|
||||
}
|
||||
})
|
||||
|
||||
if (firstRequest) {
|
||||
setFirstRequest(false);
|
||||
checkAdmin();
|
||||
setFirstRequest(false)
|
||||
checkAdmin()
|
||||
}
|
||||
|
||||
const onSubmit = (e) => {
|
||||
setLoginLoading(true);
|
||||
e.preventDefault();
|
||||
setLoginInfo("");
|
||||
setLoginLoading(true)
|
||||
e.preventDefault()
|
||||
setLoginInfo("")
|
||||
// FIXME - add some check here ROFL
|
||||
|
||||
// Just use this one?
|
||||
var data = { username: username, password: password };
|
||||
var data = {"username": username, "password": password}
|
||||
if (MFAValue !== undefined && MFAValue !== null && MFAValue.length > 0) {
|
||||
data["mfa_code"] = MFAValue;
|
||||
data["mfa_code"] = MFAValue
|
||||
}
|
||||
|
||||
var baseurl = globalUrl;
|
||||
var baseurl = globalUrl
|
||||
if (register) {
|
||||
var url = baseurl + "/api/v1/users/login";
|
||||
var url = baseurl + '/api/v1/users/login';
|
||||
fetch(url, {
|
||||
mode: "cors",
|
||||
method: "POST",
|
||||
mode: 'cors',
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
credentials: "include",
|
||||
credentials: 'include',
|
||||
crossDomain: true,
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
setLoginLoading(false);
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
setLoginLoading(false)
|
||||
if (responseJson["success"] === false) {
|
||||
setLoginInfo(responseJson["reason"]);
|
||||
setLoginInfo(responseJson["reason"])
|
||||
} else {
|
||||
if (responseJson["reason"] === "MFA_REDIRECT") {
|
||||
setLoginInfo(
|
||||
"MFA required. Please the 6-digit code from your authenticator"
|
||||
);
|
||||
setMFAField(true);
|
||||
return;
|
||||
setLoginInfo("MFA required. Please the 6-digit code from your authenticator")
|
||||
setMFAField(true)
|
||||
return
|
||||
}
|
||||
|
||||
setLoginInfo("Successful login, rerouting");
|
||||
setLoginInfo("Successful login, rerouting")
|
||||
for (var key in responseJson["cookies"]) {
|
||||
setCookie(
|
||||
responseJson["cookies"][key].key,
|
||||
responseJson["cookies"][key].value,
|
||||
{ path: "/" }
|
||||
);
|
||||
setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, { path: "/" })
|
||||
}
|
||||
|
||||
setIsLoggedIn(true);
|
||||
setIsLoggedIn(true)
|
||||
|
||||
window.location.pathname = "/workflows";
|
||||
window.location.pathname = "/workflows"
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setLoginLoading(false);
|
||||
setLoginInfo("Error logging in: " + error);
|
||||
.catch(error => {
|
||||
setLoginLoading(false)
|
||||
setLoginInfo("Error logging in: " + error)
|
||||
});
|
||||
} else {
|
||||
url = baseurl + "/api/v1/users/register";
|
||||
url = baseurl + '/api/v1/users/register';
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
if (responseJson["success"] === false) {
|
||||
setLoginInfo(responseJson["reason"]);
|
||||
setLoginInfo(responseJson["reason"])
|
||||
} else {
|
||||
setLoginInfo("Successful register!");
|
||||
setLoginInfo("Successful register!")
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setLoginInfo("Error in from backend: ", error);
|
||||
.catch(error => {
|
||||
setLoginInfo("Error in from backend: ", error)
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const onChangeUser = (e) => {
|
||||
setUsername(e.target.value);
|
||||
};
|
||||
setUsername(e.target.value)
|
||||
}
|
||||
|
||||
const onChangePass = (e) => {
|
||||
setPassword(e.target.value);
|
||||
};
|
||||
setPassword(e.target.value)
|
||||
}
|
||||
|
||||
//const onClickRegister = () => {
|
||||
// if (props.location.pathname === "/login") {
|
||||
@@ -227,58 +203,38 @@ const LoginDialog = (props) => {
|
||||
//}
|
||||
|
||||
//var loginChange = register ? (<div><p onClick={setLoginCheck(false)}>Want to register? Click here.</p></div>) : (<div><p onClick={setLoginCheck(true)}>Go back to login? Click here.</p></div>);
|
||||
var formtitle = register ? <div>Login</div> : <div>Register</div>;
|
||||
const imgsize = 100;
|
||||
const basedata = (
|
||||
var formtitle = register ? <div>Login</div> : <div>Register</div>
|
||||
const imgsize = 100
|
||||
const basedata =
|
||||
<div style={bodyDivStyle}>
|
||||
<Paper
|
||||
style={{
|
||||
<Paper style={{
|
||||
paddingLeft: "30px",
|
||||
paddingRight: "30px",
|
||||
paddingBottom: "30px",
|
||||
paddingTop: "30px",
|
||||
position: "relative",
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: -imgsize / 2 - 10,
|
||||
left: 250 - imgsize / 2,
|
||||
height: imgsize,
|
||||
width: imgsize,
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src="images/Shuffle_logo.png"
|
||||
style={{
|
||||
height: imgsize + 10,
|
||||
width: imgsize + 10,
|
||||
border: "2px solid rgba(255,255,255,0.6)",
|
||||
borderRadius: imgsize,
|
||||
}}
|
||||
/>
|
||||
}}>
|
||||
<div style={{position: "absolute", top: -imgsize/2-10, left: 250-imgsize/2, height: imgsize, width: imgsize, }}>
|
||||
<img src="images/Shuffle_logo.png" style={{height: imgsize+10, width: imgsize+10, border: "2px solid rgba(255,255,255,0.6)", borderRadius: imgsize,}}/>
|
||||
</div>
|
||||
{loginViewLoading ? (
|
||||
<div style={{ textAlign: "center", marginTop: 50 }}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{ marginBottom: 20, color: "white" }}
|
||||
>
|
||||
Waiting for the Shuffle database to become available. This may
|
||||
take up to a minute.
|
||||
{loginViewLoading ?
|
||||
<div style={{textAlign: "center", marginTop: 50, }}>
|
||||
<Typography variant="body2" style={{marginBottom: 20, color: "white",}}>
|
||||
Waiting for the Shuffle database to become available. This may take up to a minute.
|
||||
</Typography>
|
||||
|
||||
{loginInfo === undefined ||
|
||||
loginInfo === null ||
|
||||
loginInfo.length === 0 ? null : (
|
||||
<div style={{ marginTop: "10px" }}>Response: {loginInfo}</div>
|
||||
)}
|
||||
<CircularProgress color="secondary" style={{ color: "white" }} />
|
||||
{loginInfo === undefined || loginInfo === null || loginInfo.length === 0 ?
|
||||
null
|
||||
:
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
Response: {loginInfo}
|
||||
</div>
|
||||
}
|
||||
<CircularProgress color="secondary" style={{color: "white",}} />
|
||||
|
||||
<Paper
|
||||
style={{
|
||||
|
||||
<Paper style={{
|
||||
paddingLeft: "30px",
|
||||
paddingRight: "30px",
|
||||
paddingBottom: "30px",
|
||||
@@ -287,74 +243,32 @@ const LoginDialog = (props) => {
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
textAlign: "left",
|
||||
marginTop: 15,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{ marginBottom: 20, color: "white" }}
|
||||
>
|
||||
<b>
|
||||
Are you sure Shuffle is{" "}
|
||||
<a
|
||||
rel="norefferer"
|
||||
target="_blank"
|
||||
href="https://github.com/frikky/Shuffle/blob/master/.github/install-guide.md"
|
||||
style={{ textDecoration: "none", color: "#f86a3e" }}
|
||||
>
|
||||
installed correctly
|
||||
</a>
|
||||
?
|
||||
</b>
|
||||
}}>
|
||||
<Typography variant="body2" style={{marginBottom: 20, color: "white",}}>
|
||||
<b>Are you sure Shuffle is <a rel="norefferer" target="_blank" href="https://github.com/frikky/Shuffle/blob/master/.github/install-guide.md" style={{textDecoration: "none", color: "#f86a3e"}}>installed correctly</a>?</b>
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{ marginBottom: 20, color: "white" }}
|
||||
>
|
||||
<b>1.</b> Make sure shuffle-database folder has correct access:{" "}
|
||||
<br />
|
||||
<br />
|
||||
<Typography variant="body2" style={{marginBottom: 20, color: "white",}}>
|
||||
<b>1.</b> Make sure shuffle-database folder has correct access: <br/><br/>
|
||||
sudo chown 1000:1000 -R shuffle-database
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{ marginBottom: 20, color: "white" }}
|
||||
>
|
||||
<b>2</b>. Restart docker-compose:
|
||||
<br />
|
||||
<br />
|
||||
<Typography variant="body2" style={{marginBottom: 20, color: "white",}}>
|
||||
<b>2</b>. Restart docker-compose:<br/><br/>
|
||||
sudo docker-compose restart
|
||||
</Typography>
|
||||
</Paper>
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{ marginBottom: 10, color: "white", marginTop: 20 }}
|
||||
>
|
||||
Need help?{" "}
|
||||
<a
|
||||
rel="norefferer"
|
||||
target="_blank"
|
||||
href="https://discord.gg/B2CBzUm"
|
||||
style={{ textDecoration: "none", color: "#f86a3e" }}
|
||||
>
|
||||
Join the Discord!
|
||||
</a>
|
||||
<Typography variant="body2" style={{marginBottom: 10, color: "white", marginTop: 20, }}>
|
||||
Need help? <a rel="norefferer" target="_blank" href="https://discord.gg/B2CBzUm" style={{textDecoration: "none", color: "#f86a3e"}}>Join the Discord!</a>
|
||||
</Typography>
|
||||
</div>
|
||||
) : (
|
||||
<form
|
||||
onSubmit={onSubmit}
|
||||
style={{ margin: "15px 15px 15px 15px", color: "white" }}
|
||||
>
|
||||
:
|
||||
<form onSubmit={onSubmit} style={{ margin: "15px 15px 15px 15px", color: "white", }}>
|
||||
<h2>{formtitle}</h2>
|
||||
Username
|
||||
<div>
|
||||
<TextField
|
||||
color="primary"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
marginTop: 5,
|
||||
}}
|
||||
style={{ backgroundColor: theme.palette.inputColor, marginTop: 5, }}
|
||||
autoFocus
|
||||
InputProps={{
|
||||
classes: {
|
||||
@@ -380,10 +294,7 @@ const LoginDialog = (props) => {
|
||||
<div>
|
||||
<TextField
|
||||
color="primary"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
marginTop: 5,
|
||||
}}
|
||||
style={{ backgroundColor: theme.palette.inputColor, marginTop: 5,}}
|
||||
InputProps={{
|
||||
classes: {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
@@ -405,20 +316,17 @@ const LoginDialog = (props) => {
|
||||
onChange={onChangePass}
|
||||
/>
|
||||
</div>
|
||||
{MFAField === true ? (
|
||||
<div style={{ marginTop: 15 }}>
|
||||
{MFAField === true ?
|
||||
<div style={{marginTop: 15}}>
|
||||
5-factor code
|
||||
<TextField
|
||||
color="primary"
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
marginTop: 5,
|
||||
}}
|
||||
style={{backgroundColor: theme.palette.inputColor, marginTop: 5, }}
|
||||
InputProps={{
|
||||
classes: {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
},
|
||||
style: {
|
||||
style:{
|
||||
height: "50px",
|
||||
color: "white",
|
||||
fontSize: "1em",
|
||||
@@ -432,59 +340,52 @@ const LoginDialog = (props) => {
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
onChange={(event) => {
|
||||
setMFAValue(event.target.value);
|
||||
setMFAValue(event.target.value)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
: null}
|
||||
<div style={{ display: "flex", marginTop: "15px" }}>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
type="submit"
|
||||
style={{ flex: "1" }}
|
||||
disabled={!handleValidateForm() || loginLoading}
|
||||
>
|
||||
{loginLoading ? (
|
||||
<CircularProgress
|
||||
color="secondary"
|
||||
style={{ color: "white" }}
|
||||
/>
|
||||
) : (
|
||||
"SUBMIT"
|
||||
)}
|
||||
<Button color="primary" variant="contained" type="submit" style={{ flex: "1", }} disabled={!handleValidateForm() || loginLoading}>
|
||||
{loginLoading ? <CircularProgress color="secondary" style={{color: "white",}} /> : "SUBMIT"}
|
||||
</Button>
|
||||
</div>
|
||||
<div style={{ marginTop: "10px" }}>{loginInfo}</div>
|
||||
{ssoUrl !== undefined && ssoUrl !== null && ssoUrl.length > 0 ? (
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
{loginInfo}
|
||||
</div>
|
||||
{ssoUrl !== undefined && ssoUrl !== null && ssoUrl.length > 0 ?
|
||||
<div>
|
||||
<Typography style={{ textAlign: "center" }}>Or</Typography>
|
||||
<div style={{ textAlign: "center", margin: 10 }}>
|
||||
<Button
|
||||
fullWidth
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
type="button"
|
||||
style={{ flex: "1", marginTop: 5 }}
|
||||
onClick={() => {
|
||||
console.log("CLICK");
|
||||
window.location = ssoUrl;
|
||||
}}
|
||||
>
|
||||
<Typography style={{textAlign: "center", }}>
|
||||
Or
|
||||
</Typography>
|
||||
<div style={{textAlign: "center", margin: 10, }}>
|
||||
<Button fullWidth color="secondary" variant="outlined" type="button" style={{ flex: "1", marginTop: 5}} onClick={() => {
|
||||
console.log("CLICK")
|
||||
window.location = ssoUrl
|
||||
}}>
|
||||
Use SSO
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
: null}
|
||||
</form>
|
||||
)}
|
||||
}
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
|
||||
const loadedCheck = isLoaded ? <div>{basedata}</div> : <div></div>;
|
||||
const loadedCheck = isLoaded ?
|
||||
<div>
|
||||
{basedata}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default LoginDialog;
|
||||
|
||||
+691
-1154
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,11 @@
|
||||
import React from "react";
|
||||
import React, { } from 'react';
|
||||
|
||||
const Oauth2 = (props) => {
|
||||
return <div>tmp</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
tmp
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Oauth2;
|
||||
|
||||
+29
-18
@@ -1,9 +1,9 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
const Body = {
|
||||
maxWidth: "1000px",
|
||||
minWidth: "768px",
|
||||
margin: "auto",
|
||||
maxWidth: '1000px',
|
||||
minWidth: '768px',
|
||||
margin: 'auto',
|
||||
display: "flex",
|
||||
heigth: "100%",
|
||||
color: "white",
|
||||
@@ -13,49 +13,60 @@ const Body = {
|
||||
const SideBar = {
|
||||
maxWidth: "250px",
|
||||
flex: "1",
|
||||
};
|
||||
}
|
||||
|
||||
const hrefStyle = {
|
||||
color: "#385f71",
|
||||
textDecoration: "none",
|
||||
};
|
||||
textDecoration: "none"
|
||||
}
|
||||
|
||||
const Post = (props) => {
|
||||
const { currentPost, isLoaded } = props;
|
||||
|
||||
const postData = (
|
||||
const postData =
|
||||
<div style={Body}>
|
||||
<div style={SideBar}>
|
||||
<ul style={{ listStyle: "none", paddingLeft: "0" }}>
|
||||
<li style={{ marginTop: "10px" }}>
|
||||
<ul style={{listStyle: "none", paddingLeft: "0"}}>
|
||||
<li style={{marginTop: "10px"}}>
|
||||
<a style={hrefStyle} href="/">
|
||||
<h2>Home</h2>
|
||||
</a>
|
||||
</li>
|
||||
<li style={{ marginTop: "10px" }}>
|
||||
<li style={{marginTop: "10px"}}>
|
||||
<a style={hrefStyle} href="/docs">
|
||||
<h2>Schedules</h2>
|
||||
</a>
|
||||
</li>
|
||||
<li style={{ marginTop: "10px" }}>
|
||||
<li style={{marginTop: "10px"}}>
|
||||
<a style={hrefStyle} href="/docs/about">
|
||||
<h2>About</h2>
|
||||
</a>
|
||||
</li>
|
||||
<li style={{ marginTop: "10px" }}>
|
||||
<li style={{marginTop: "10px"}}>
|
||||
<a style={hrefStyle} href="/docs/privacy-policy">
|
||||
<h2>Privacy Policy</h2>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style={{ flex: "1" }}>{currentPost}</div>
|
||||
<div style={{flex: "1"}}>
|
||||
{currentPost}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const loadedCheck = isLoaded ? <div>{postData}</div> : <div></div>;
|
||||
const loadedCheck = isLoaded ?
|
||||
<div>
|
||||
{postData}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Post;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
const PrivacyPolicy = () => {
|
||||
return (
|
||||
@@ -7,39 +7,23 @@ const PrivacyPolicy = () => {
|
||||
|
||||
<p>Effective date: 17.08.2019</p>
|
||||
|
||||
|
||||
<p>We operate the shuffler.io website.</p>
|
||||
|
||||
<p>
|
||||
This page informs you of our policies regarding the collection, use, and
|
||||
disclosure of personal data when you use our service and the choices you
|
||||
have associated with that data.
|
||||
</p>
|
||||
<p>This page informs you of our policies regarding the collection, use, and disclosure of personal data when you use our service and the choices you have associated with that data.</p>
|
||||
|
||||
<p>We use your data to provide and improve the service. By using the service, you agree to the collection and use of information in accordance with this policy. Unless otherwise defined in this Privacy Policy, terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, accessible from shuffler.io</p>
|
||||
|
||||
<p>
|
||||
We use your data to provide and improve the service. By using the
|
||||
service, you agree to the collection and use of information in
|
||||
accordance with this policy. Unless otherwise defined in this Privacy
|
||||
Policy, terms used in this Privacy Policy have the same meanings as in
|
||||
our Terms and Conditions, accessible from shuffler.io
|
||||
</p>
|
||||
|
||||
<h2>Information Collection And Use</h2>
|
||||
|
||||
<p>
|
||||
We collect several different types of information for various purposes
|
||||
to provide and improve our service to you.
|
||||
</p>
|
||||
<p>We collect several different types of information for various purposes to provide and improve our service to you.</p>
|
||||
|
||||
<h3>Types of Data Collected</h3>
|
||||
|
||||
<h4>Personal Data</h4>
|
||||
|
||||
<p>
|
||||
While using our service, we may ask you to provide us with certain
|
||||
personally identifiable information that can be used to contact or
|
||||
identify you ("Personal Data"). Personally identifiable information may
|
||||
include, but is not limited to:
|
||||
</p>
|
||||
<p>While using our service, we may ask you to provide us with certain personally identifiable information that can be used to contact or identify you ("Personal Data"). Personally identifiable information may include, but is not limited to:</p>
|
||||
|
||||
<ul>
|
||||
<li>Cookies and Usage Data</li>
|
||||
@@ -47,46 +31,17 @@ const PrivacyPolicy = () => {
|
||||
|
||||
<h4>Usage Data</h4>
|
||||
|
||||
<p>
|
||||
We may also collect information how the service is accessed and used
|
||||
("Usage Data"). This Usage Data may include information such as your
|
||||
computer's Internet Protocol address (e.g. IP address), browser type,
|
||||
browser version, the pages of our service that you visit, the time and
|
||||
date of your visit, the time spent on those pages, unique device
|
||||
identifiers and other diagnostic data.
|
||||
</p>
|
||||
<p>We may also collect information how the service is accessed and used ("Usage Data"). This Usage Data may include information such as your computer's Internet Protocol address (e.g. IP address), browser type, browser version, the pages of our service that you visit, the time and date of your visit, the time spent on those pages, unique device identifiers and other diagnostic data.</p>
|
||||
|
||||
<h4>Tracking & Cookies Data</h4>
|
||||
<p>
|
||||
We use cookies and similar tracking technologies to track the activity
|
||||
on our service and hold certain information.
|
||||
</p>
|
||||
<p>
|
||||
Cookies are files with small amount of data which may include an
|
||||
anonymous unique identifier. Cookies are sent to your browser from a
|
||||
website and stored on your device. Tracking technologies also used are
|
||||
beacons, tags, and scripts to collect and track information and to
|
||||
improve and analyze our service.
|
||||
</p>
|
||||
<p>
|
||||
You can instruct your browser to refuse all cookies or to indicate when
|
||||
a cookie is being sent. However, if you do not accept cookies, you may
|
||||
not be able to use some portions of our service.
|
||||
</p>
|
||||
<p>We use cookies and similar tracking technologies to track the activity on our service and hold certain information.</p>
|
||||
<p>Cookies are files with small amount of data which may include an anonymous unique identifier. Cookies are sent to your browser from a website and stored on your device. Tracking technologies also used are beacons, tags, and scripts to collect and track information and to improve and analyze our service.</p>
|
||||
<p>You can instruct your browser to refuse all cookies or to indicate when a cookie is being sent. However, if you do not accept cookies, you may not be able to use some portions of our service.</p>
|
||||
<p>Examples of Cookies we use:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Session Cookies.</strong> We use Session Cookies to operate
|
||||
our service.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Preference Cookies.</strong> We use Preference Cookies to
|
||||
remember your preferences and various settings.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Security Cookies.</strong> We use Security Cookies for
|
||||
security purposes.
|
||||
</li>
|
||||
<li><strong>Session Cookies.</strong> We use Session Cookies to operate our service.</li>
|
||||
<li><strong>Preference Cookies.</strong> We use Preference Cookies to remember your preferences and various settings.</li>
|
||||
<li><strong>Security Cookies.</strong> We use Security Cookies for security purposes.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use of Data</h2>
|
||||
@@ -95,170 +50,73 @@ const PrivacyPolicy = () => {
|
||||
<ul>
|
||||
<li>To provide and maintain the service</li>
|
||||
<li>To notify you about changes to our service</li>
|
||||
<li>
|
||||
To allow you to participate in interactive features of our service
|
||||
when you choose to do so
|
||||
</li>
|
||||
<li>To allow you to participate in interactive features of our service when you choose to do so</li>
|
||||
<li>To provide customer care and support</li>
|
||||
<li>
|
||||
To provide analysis or valuable information so that we can improve the
|
||||
service
|
||||
</li>
|
||||
<li>To provide analysis or valuable information so that we can improve the service</li>
|
||||
<li>To monitor the usage of the service</li>
|
||||
<li>To detect, prevent and address technical issues</li>
|
||||
</ul>
|
||||
|
||||
<h2>Transfer Of Data</h2>
|
||||
<p>
|
||||
Your information, including Personal Data, may be transferred to — and
|
||||
maintained on — computers located outside of your state, province,
|
||||
country or other governmental jurisdiction where the data protection
|
||||
laws may differ than those from your jurisdiction.
|
||||
</p>
|
||||
<p>
|
||||
If you are located outside Norway and choose to provide information to
|
||||
us, please note that we transfer the data, including Personal Data, to
|
||||
Norway and process it there.
|
||||
</p>
|
||||
<p>
|
||||
Your consent to this Privacy Policy followed by your submission of such
|
||||
information represents your agreement to that transfer.
|
||||
</p>
|
||||
<p>
|
||||
Shuffler will take all steps reasonably necessary to ensure that your
|
||||
data is treated securely and in accordance with this Privacy Policy and
|
||||
no transfer of your Personal Data will take place to an organization or
|
||||
a country unless there are adequate controls in place including the
|
||||
security of your data and other personal information.
|
||||
</p>
|
||||
<p>Your information, including Personal Data, may be transferred to — and maintained on — computers located outside of your state, province, country or other governmental jurisdiction where the data protection laws may differ than those from your jurisdiction.</p>
|
||||
<p>If you are located outside Norway and choose to provide information to us, please note that we transfer the data, including Personal Data, to Norway and process it there.</p>
|
||||
<p>Your consent to this Privacy Policy followed by your submission of such information represents your agreement to that transfer.</p>
|
||||
<p>Shuffler will take all steps reasonably necessary to ensure that your data is treated securely and in accordance with this Privacy Policy and no transfer of your Personal Data will take place to an organization or a country unless there are adequate controls in place including the security of your data and other personal information.</p>
|
||||
|
||||
<h2>Disclosure Of Data</h2>
|
||||
|
||||
<h3>Legal Requirements</h3>
|
||||
<p>
|
||||
Shuffler may disclose your Personal Data in the good faith belief that
|
||||
such action is necessary to:
|
||||
</p>
|
||||
<p>Shuffler may disclose your Personal Data in the good faith belief that such action is necessary to:</p>
|
||||
<ul>
|
||||
<li>To comply with a legal obligation</li>
|
||||
<li>To protect and defend the rights or property of Shuffler</li>
|
||||
<li>
|
||||
To prevent or investigate possible wrongdoing in connection with the
|
||||
service
|
||||
</li>
|
||||
<li>
|
||||
To protect the personal safety of users of the service or the public
|
||||
</li>
|
||||
<li>To prevent or investigate possible wrongdoing in connection with the service</li>
|
||||
<li>To protect the personal safety of users of the service or the public</li>
|
||||
<li>To protect against legal liability</li>
|
||||
</ul>
|
||||
|
||||
<h2>Security Of Data</h2>
|
||||
<p>
|
||||
The security of your data is important to us, but remember that no
|
||||
method of transmission over the Internet, or method of electronic
|
||||
storage is 100% secure. While we strive to use commercially acceptable
|
||||
means to protect your Personal Data, we cannot guarantee its absolute
|
||||
security.
|
||||
</p>
|
||||
<p>The security of your data is important to us, but remember that no method of transmission over the Internet, or method of electronic storage is 100% secure. While we strive to use commercially acceptable means to protect your Personal Data, we cannot guarantee its absolute security.</p>
|
||||
|
||||
<h2>Service Providers</h2>
|
||||
<p>
|
||||
We may employ third party companies and individuals to facilitate our
|
||||
service ("service Providers"), to provide the service on our behalf, to
|
||||
perform service-related services or to assist us in analyzing how our
|
||||
service is used.
|
||||
</p>
|
||||
<p>
|
||||
These third parties have access to your Personal Data only to perform
|
||||
these tasks on our behalf and are obligated not to disclose or use it
|
||||
for any other purpose.
|
||||
</p>
|
||||
<p>We may employ third party companies and individuals to facilitate our service ("service Providers"), to provide the service on our behalf, to perform service-related services or to assist us in analyzing how our service is used.</p>
|
||||
<p>These third parties have access to your Personal Data only to perform these tasks on our behalf and are obligated not to disclose or use it for any other purpose.</p>
|
||||
|
||||
<h3>Analytics</h3>
|
||||
<p>
|
||||
We may use third-party service Providers to monitor and analyze the use
|
||||
of our service.
|
||||
</p>
|
||||
<p>We may use third-party service Providers to monitor and analyze the use of our service.</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>
|
||||
<strong>Google Analytics</strong>
|
||||
</p>
|
||||
<p>
|
||||
Google Analytics is a web analytics service offered by Google that
|
||||
tracks and reports website traffic. Google uses the data collected
|
||||
to track and monitor the use of our service. This data is shared
|
||||
with other Google services. Google may use the collected data to
|
||||
contextualize and personalize the ads of its own advertising
|
||||
network.
|
||||
</p>
|
||||
<p>
|
||||
You can opt-out of having made your activity on the service
|
||||
available to Google Analytics by installing the Google Analytics
|
||||
opt-out browser add-on. The add-on prevents the Google Analytics
|
||||
JavaScript (ga.js, analytics.js, and dc.js) from sharing information
|
||||
with Google Analytics about visits activity.
|
||||
</p>{" "}
|
||||
<p>
|
||||
For more information on the privacy practices of Google, please
|
||||
visit the Google Privacy & Terms web page:{" "}
|
||||
<a href="https://policies.google.com/privacy?hl=en">
|
||||
https://policies.google.com/privacy?hl=en
|
||||
</a>
|
||||
</p>
|
||||
<p><strong>Google Analytics</strong></p>
|
||||
<p>Google Analytics is a web analytics service offered by Google that tracks and reports website traffic. Google uses the data collected to track and monitor the use of our service. This data is shared with other Google services. Google may use the collected data to contextualize and personalize the ads of its own advertising network.</p>
|
||||
<p>You can opt-out of having made your activity on the service available to Google Analytics by installing the Google Analytics opt-out browser add-on. The add-on prevents the Google Analytics JavaScript (ga.js, analytics.js, and dc.js) from sharing information with Google Analytics about visits activity.</p> <p>For more information on the privacy practices of Google, please visit the Google Privacy & Terms web page: <a href="https://policies.google.com/privacy?hl=en">https://policies.google.com/privacy?hl=en</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Links To Other Sites</h2>
|
||||
<p>
|
||||
Our service may contain links to other sites that are not operated by
|
||||
us. If you click on a third party link, you will be directed to that
|
||||
third party's site. We strongly advise you to review the Privacy Policy
|
||||
of every site you visit.
|
||||
</p>
|
||||
<p>
|
||||
We have no control over and assume no responsibility for the content,
|
||||
privacy policies or practices of any third party sites or services.
|
||||
</p>
|
||||
<p>Our service may contain links to other sites that are not operated by us. If you click on a third party link, you will be directed to that third party's site. We strongly advise you to review the Privacy Policy of every site you visit.</p>
|
||||
<p>We have no control over and assume no responsibility for the content, privacy policies or practices of any third party sites or services.</p>
|
||||
|
||||
|
||||
<h2>Children's Privacy</h2>
|
||||
<p>
|
||||
Our service does not address anyone under the age of 18 ("Children").
|
||||
</p>
|
||||
<p>
|
||||
We do not knowingly collect personally identifiable information from
|
||||
anyone under the age of 18. If you are a parent or guardian and you are
|
||||
aware that your Children has provided us with Personal Data, please
|
||||
contact us. If we become aware that we have collected Personal Data from
|
||||
children without verification of parental consent, we take steps to
|
||||
remove that information from our servers.
|
||||
</p>
|
||||
<p>Our service does not address anyone under the age of 18 ("Children").</p>
|
||||
<p>We do not knowingly collect personally identifiable information from anyone under the age of 18. If you are a parent or guardian and you are aware that your Children has provided us with Personal Data, please contact us. If we become aware that we have collected Personal Data from children without verification of parental consent, we take steps to remove that information from our servers.</p>
|
||||
|
||||
|
||||
<h2>Changes To This Privacy Policy</h2>
|
||||
<p>
|
||||
We may update our Privacy Policy from time to time. We will notify you
|
||||
of any changes by posting the new Privacy Policy on this page.
|
||||
</p>
|
||||
<p>
|
||||
We will let you know via email and/or a prominent notice on our service,
|
||||
prior to the change becoming effective and update the "effective date"
|
||||
at the top of this Privacy Policy.
|
||||
</p>
|
||||
<p>
|
||||
You are advised to review this Privacy Policy periodically for any
|
||||
changes. Changes to this Privacy Policy are effective when they are
|
||||
posted on this page.
|
||||
</p>
|
||||
<p>We may update our Privacy Policy from time to time. We will notify you of any changes by posting the new Privacy Policy on this page.</p>
|
||||
<p>We will let you know via email and/or a prominent notice on our service, prior to the change becoming effective and update the "effective date" at the top of this Privacy Policy.</p>
|
||||
<p>You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are effective when they are posted on this page.</p>
|
||||
|
||||
|
||||
<h2>Contact Us</h2>
|
||||
<p>
|
||||
If you have any questions about this Privacy Policy, please contact us:
|
||||
</p>
|
||||
<p>If you have any questions about this Privacy Policy, please contact us:</p>
|
||||
<ul>
|
||||
<li>By email: fredrik_9490@hotmail.com</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default PrivacyPolicy;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, {useState, useEffect} from 'react';
|
||||
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
|
||||
const bodyDivStyle = {
|
||||
margin: "auto",
|
||||
textAlign: "center",
|
||||
width: "768px",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//const tmpdata = {
|
||||
// "username": "frikky",
|
||||
@@ -22,7 +23,7 @@ const bodyDivStyle = {
|
||||
// FIXME - remove tmpdata
|
||||
// FIXME: Use isLoggedIn :)
|
||||
const Settings = (props) => {
|
||||
const { globalUrl, isLoaded, surfaceColor } = props;
|
||||
const { globalUrl, isLoaded, surfaceColor, } = props;
|
||||
|
||||
const [firstRequest, setFirstRequest] = useState(true);
|
||||
const boxStyle = {
|
||||
@@ -36,52 +37,57 @@ const Settings = (props) => {
|
||||
backgroundColor: surfaceColor,
|
||||
color: "white",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
};
|
||||
flexDirection: "column"
|
||||
}
|
||||
|
||||
const registerCall = () => {
|
||||
const url = globalUrl + "/api/v1/register/" + props.match.params.key;
|
||||
const url = globalUrl+'/api/v1/register/'+props.match.params.key
|
||||
fetch(url, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
method: 'GET',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
console.log(responseJson);
|
||||
})
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
console.log(responseJson)
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
console.log("SOMETHING WRONG");
|
||||
.catch(error => {
|
||||
console.log("SOMETHING WRONG")
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// This should "always" have data
|
||||
useEffect(() => {
|
||||
if (firstRequest) {
|
||||
setFirstRequest(false);
|
||||
registerCall();
|
||||
setFirstRequest(false)
|
||||
registerCall()
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// Random names for type & autoComplete. Didn't research :^)
|
||||
const landingpageData = (
|
||||
<div style={{ display: "flex", marginTop: "80px" }}>
|
||||
const landingpageData =
|
||||
<div style={{display: "flex", marginTop: "80px"}}>
|
||||
<Paper style={boxStyle}>
|
||||
<h2>Registration verification</h2>
|
||||
<p>Thanks for verifying, redirecting you to our login!</p>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
|
||||
const loadedCheck = isLoaded ? (
|
||||
<div style={bodyDivStyle}>{landingpageData}</div>
|
||||
) : (
|
||||
<div></div>
|
||||
);
|
||||
const loadedCheck = isLoaded ?
|
||||
<div style={bodyDivStyle}>
|
||||
{landingpageData}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return(
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Settings;
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
import React, { useState } from "react";
|
||||
import React, {useState} from 'react';
|
||||
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
const LoginDialog = (props) => {
|
||||
const {
|
||||
classes,
|
||||
onClose,
|
||||
open,
|
||||
globalUrl,
|
||||
isLoggedIn,
|
||||
setIsLoggedIn,
|
||||
...other
|
||||
} = props;
|
||||
const LoginDialog = props => {
|
||||
const { classes, onClose, open, globalUrl, isLoggedIn, setIsLoggedIn, ...other } = props;
|
||||
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
@@ -28,91 +20,86 @@ const LoginDialog = (props) => {
|
||||
const [loginInfo, setLoginInfo] = useState("");
|
||||
|
||||
const handleValidateForm = () => {
|
||||
return username.length > 1 && password.length > 8;
|
||||
};
|
||||
return (username.length > 1 && password.length > 8);
|
||||
}
|
||||
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
e.preventDefault()
|
||||
|
||||
// Just use this one?
|
||||
var data =
|
||||
'{"username": "' + username + '", "password": "' + password + '"}';
|
||||
var baseurl = globalUrl;
|
||||
var data = '{"username": "' + username + '", "password": "' + password + '"}';
|
||||
var baseurl = globalUrl
|
||||
if (loginCheck) {
|
||||
var url = baseurl + "/login";
|
||||
var url = baseurl+'/login';
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: data,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
console.log(responseJson);
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
console.log(responseJson)
|
||||
//console.log(e)
|
||||
if (responseJson["success"] === false) {
|
||||
setLoginInfo(responseJson["reason"]);
|
||||
setLoginInfo(responseJson["reason"])
|
||||
} else {
|
||||
setLoginInfo("Successful login :)");
|
||||
onClose();
|
||||
setIsLoggedIn(true);
|
||||
setLoginInfo("Successful login :)")
|
||||
onClose()
|
||||
setIsLoggedIn(true)
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setLoginInfo("Error in userdata");
|
||||
.catch(error => {
|
||||
setLoginInfo("Error in userdata")
|
||||
});
|
||||
} else {
|
||||
url = baseurl + "/register";
|
||||
url = baseurl+'/register';
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
body: data,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((responseJson) => {
|
||||
.then(response =>
|
||||
response.json().then(responseJson => {
|
||||
if (responseJson["success"] === false) {
|
||||
setLoginInfo(responseJson["reason"]);
|
||||
setLoginInfo(responseJson["reason"])
|
||||
} else {
|
||||
setLoginInfo("Successful register. Please check your mail :)");
|
||||
onClose();
|
||||
setIsLoggedIn(true);
|
||||
setLoginInfo("Successful register. Please check your mail :)")
|
||||
onClose()
|
||||
setIsLoggedIn(true)
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
.catch((error) => {
|
||||
setLoginInfo("Error in userdata");
|
||||
.catch(error => {
|
||||
setLoginInfo("Error in userdata")
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const onChangeUser = (e) => {
|
||||
setUsername(e.target.value);
|
||||
};
|
||||
setUsername(e.target.value)
|
||||
}
|
||||
|
||||
const onChangePass = (e) => {
|
||||
setPassword(e.target.value);
|
||||
};
|
||||
setPassword(e.target.value)
|
||||
}
|
||||
|
||||
const onClickRegister = () => {
|
||||
setLoginCheck(!loginCheck);
|
||||
};
|
||||
setLoginCheck(!loginCheck)
|
||||
}
|
||||
|
||||
//var loginChange = loginCheck ? (<div><p onClick={setLoginCheck(false)}>Want to register? Click here.</p></div>) : (<div><p onClick={setLoginCheck(true)}>Go back to login? Click here.</p></div>);
|
||||
var formtitle = loginCheck ? <div>Login</div> : <div>Register</div>;
|
||||
var formButton = loginCheck ? (
|
||||
<div>Click to Register</div>
|
||||
) : (
|
||||
<div>Click to Login</div>
|
||||
);
|
||||
var formtitle = loginCheck ? <div>Login</div> : <div>Register</div>
|
||||
var formButton = loginCheck ? <div>Click to Register</div> : <div>Click to Login</div>
|
||||
|
||||
return (
|
||||
<Dialog modal open={open} onClose={onClose} {...other}>
|
||||
<DialogTitle>{formtitle}</DialogTitle>
|
||||
<form onSubmit={onSubmit} style={{ margin: "15px 15px 15px 15px" }}>
|
||||
<form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px"}}>
|
||||
Username
|
||||
<div>
|
||||
<TextField
|
||||
@@ -135,42 +122,18 @@ const LoginDialog = (props) => {
|
||||
onChange={onChangePass}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: "flex", marginTop: "15px" }}>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
type="submit"
|
||||
style={{ flex: "1", marginRight: "5px" }}
|
||||
disabled={!handleValidateForm()}
|
||||
>
|
||||
SUBMIT
|
||||
</Button>
|
||||
<div style={{display: "flex", marginTop: "15px"}}>
|
||||
<Button color="secondary" variant="contained" type="submit" style={{flex: "1", marginRight: "5px"}} disabled={!handleValidateForm()}>SUBMIT</Button>
|
||||
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
type="button"
|
||||
style={{ flex: "1" }}
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button color="primary" variant="contained" type="button" style={{flex: "1"}} onClick={onClose}>Cancel</Button>
|
||||
</div>
|
||||
{loginInfo}
|
||||
</form>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
onClick={onClickRegister}
|
||||
type="button"
|
||||
style={{ flex: "1" }}
|
||||
>
|
||||
{formButton}
|
||||
</Button>
|
||||
<div style={{display: "flex"}}>
|
||||
<Button color="secondary" variant="contained" onClick={onClickRegister} type="button" style={{flex: "1"}}>{formButton}</Button>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default LoginDialog;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect} from 'react';
|
||||
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import ButtonBase from "@material-ui/core/ButtonBase";
|
||||
import List from "@material-ui/core/List";
|
||||
import ListItem from "@material-ui/core/ListItem";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import ButtonBase from '@material-ui/core/ButtonBase';
|
||||
import List from '@material-ui/core/List';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import Button from '@material-ui/core/Button';
|
||||
//import Breadcrumbs from '@material-ui/core/Breadcrumbs';
|
||||
|
||||
const Schedules = (props) => {
|
||||
@@ -15,59 +15,59 @@ const Schedules = (props) => {
|
||||
const [schedules, setSchedules] = React.useState({});
|
||||
|
||||
const getAvailableSchedules = () => {
|
||||
fetch(globalUrl + "/api/v1/schedules", {
|
||||
method: "GET",
|
||||
fetch(globalUrl+"/api/v1/schedules", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
setSchedules(responseJson);
|
||||
setSchedules(responseJson)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// FIXME - add automated redirection, as empty apps look horrible currently
|
||||
const newSchedule = () => {
|
||||
fetch(globalUrl + "/api/v1/schedules/new", {
|
||||
fetch(globalUrl+"/api/v1/schedules/new", {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
headers: {"content-type": "application/json"},
|
||||
body: JSON.stringify(),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
console.log(responseJson);
|
||||
setSchedules({});
|
||||
console.log(responseJson)
|
||||
setSchedules({})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const deleteSchedule = (id) => {
|
||||
if (id === undefined) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
fetch(globalUrl + "/api/v1/schedules/" + id + "/delete", {
|
||||
method: "DELETE",
|
||||
fetch(globalUrl+"/api/v1/schedules/"+id+"/delete", {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
setSchedules({});
|
||||
setSchedules({})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// FIXME - use this?
|
||||
//const getNewScheduleInfo = () => {
|
||||
@@ -89,9 +89,10 @@ const Schedules = (props) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (Object.getOwnPropertyNames(schedules).length <= 0) {
|
||||
getAvailableSchedules();
|
||||
getAvailableSchedules()
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
const bodyDivStyle = {
|
||||
marginLeft: "20px",
|
||||
@@ -99,15 +100,15 @@ const Schedules = (props) => {
|
||||
width: "1350px",
|
||||
minWidth: "1350px",
|
||||
maxWidth: "1350px",
|
||||
};
|
||||
}
|
||||
|
||||
const scheduleApp = (app) => {
|
||||
console.log(app);
|
||||
return (
|
||||
<Grid container spacing={2} style={{ margin: "10px 10px 10px 10px" }}>
|
||||
console.log(app)
|
||||
return(
|
||||
<Grid container spacing={2} style={{margin: "10px 10px 10px 10px"}}>
|
||||
<Grid item>
|
||||
<ButtonBase>
|
||||
<img alt="" style={{ width: "100px", height: "100px" }} />
|
||||
<img alt="" style={{width: "100px", height: "100px"}} />
|
||||
</ButtonBase>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm container>
|
||||
@@ -116,117 +117,104 @@ const Schedules = (props) => {
|
||||
<div>
|
||||
<h2>{app.name}</h2>
|
||||
</div>
|
||||
<div>{app.description}</div>
|
||||
<div>
|
||||
{app.description}
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item>{app.action}</Grid>
|
||||
<Grid item>
|
||||
{app.action}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
const splitter = (
|
||||
<div
|
||||
style={{
|
||||
width: "1px",
|
||||
backgroundColor: "grey",
|
||||
margin: "5px 5px 5px 5px",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const splitter = <div style={{width: "1px", backgroundColor: "grey", margin:"5px 5px 5px 5px"}} />
|
||||
|
||||
const hrefStyle = {
|
||||
color: "#385f71",
|
||||
textDecoration: "none",
|
||||
};
|
||||
textDecoration: "none"
|
||||
}
|
||||
|
||||
// FIXME - add Schedule modal
|
||||
const schedulePaper = (schedule) => {
|
||||
return (
|
||||
return(
|
||||
<div>
|
||||
<Paper
|
||||
style={{
|
||||
maxWidth: "1000px",
|
||||
display: "flex",
|
||||
padding: "10px 10px 10px 10px",
|
||||
}}
|
||||
>
|
||||
<div style={{ flex: "5" }}>
|
||||
<Paper style={{maxWidth: "1000px", display: "flex", padding: "10px 10px 10px 10px"}}>
|
||||
<div style={{flex: "5"}}>
|
||||
{scheduleApp(schedule.appinfo.sourceapp)}
|
||||
</div>
|
||||
<div style={{ flex: "1", alignItems: "center" }}>ARROW</div>
|
||||
<div style={{ flex: "5" }}>
|
||||
<div style={{flex: "1", alignItems: "center"}}>
|
||||
ARROW
|
||||
</div>
|
||||
<div style={{flex: "5"}}>
|
||||
{scheduleApp(schedule.appinfo.destinationapp)}
|
||||
</div>
|
||||
{splitter}
|
||||
<div style={{ flex: "1" }}>
|
||||
<List style={{ backgroundColor: "#ffffff" }}>
|
||||
<ListItem style={{ flex: "1", textAlign: "center" }}>
|
||||
<a href={"/schedules/" + schedule.id} style={hrefStyle}>
|
||||
<Button disabled={false} color="primary">
|
||||
<div style={{flex: "1"}}>
|
||||
<List style={{backgroundColor: "#ffffff"}}>
|
||||
<ListItem style={{flex: "1", textAlign: "center"}}>
|
||||
<a href={"/schedules/"+schedule.id} style={hrefStyle} >
|
||||
<Button
|
||||
disabled={false}
|
||||
color="primary"
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</a>
|
||||
</ListItem>
|
||||
<ListItem style={{ flex: "1", textAlign: "center" }}>
|
||||
<ListItem style={{flex: "1", textAlign: "center"}}>
|
||||
<Button
|
||||
disabled={false}
|
||||
onClick={() => {
|
||||
deleteSchedule(schedule.id);
|
||||
}}
|
||||
onClick={() => {deleteSchedule(schedule.id)}}
|
||||
color="primary"
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
>Delete</Button>
|
||||
</ListItem>
|
||||
|
||||
</List>
|
||||
</div>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
console.log(schedules);
|
||||
console.log(schedules);
|
||||
console.log(schedules.schedules);
|
||||
const schedulemap =
|
||||
Object.getOwnPropertyNames(schedules).length > 0 &&
|
||||
schedules.schedules &&
|
||||
schedules.schedules.length > 0 ? (
|
||||
<div>{schedules.schedules.map((data) => schedulePaper(data))}</div>
|
||||
) : (
|
||||
<div style={{ marginTop: "10%", marginLeft: "50%" }}>
|
||||
console.log(schedules)
|
||||
console.log(schedules)
|
||||
console.log(schedules.schedules)
|
||||
const schedulemap = Object.getOwnPropertyNames(schedules).length > 0 && schedules.schedules && schedules.schedules.length > 0 ?
|
||||
<div>
|
||||
{schedules.schedules.map(data => (
|
||||
schedulePaper(data)
|
||||
))}
|
||||
</div>
|
||||
:
|
||||
<div style={{marginTop: "10%", marginLeft: "50%"}} >
|
||||
<Button
|
||||
disabled={false}
|
||||
onClick={() => {
|
||||
newSchedule();
|
||||
}}
|
||||
onClick={() => {newSchedule()}}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
>
|
||||
CREATE NEW SCHEDULE
|
||||
</Button>
|
||||
>CREATE NEW SCHEDULE</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
const scheduleView =
|
||||
Object.getOwnPropertyNames(schedules).length > 0 ? (
|
||||
const scheduleView = Object.getOwnPropertyNames(schedules).length > 0 ?
|
||||
<div style={bodyDivStyle}>
|
||||
<Button
|
||||
disabled={false}
|
||||
onClick={() => {
|
||||
newSchedule();
|
||||
}}
|
||||
onClick={() => {newSchedule()}}
|
||||
color="primary"
|
||||
>
|
||||
New
|
||||
</Button>
|
||||
>New</Button>
|
||||
{schedulemap}
|
||||
</div>
|
||||
) : null;
|
||||
: null
|
||||
|
||||
// Maybe use gridview or something, idk
|
||||
return <div>{scheduleView}</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
{scheduleView}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Schedules;
|
||||
export default Schedules
|
||||
|
||||
@@ -1,68 +1,62 @@
|
||||
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
|
||||
import React, {useRef, useState, useEffect, useLayoutEffect} from 'react';
|
||||
|
||||
import { Typography, CircularProgress } from "@material-ui/core";
|
||||
import { Typography, CircularProgress } from '@material-ui/core';
|
||||
|
||||
const SetAuthentication = (props) => {
|
||||
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
|
||||
|
||||
const [firstRequest, setFirstRequest] = useState(true);
|
||||
const [finished, setFinished] = useState(false);
|
||||
const [response, setResponse] = useState("");
|
||||
const [failed, setFailed] = useState(false);
|
||||
const [firstRequest, setFirstRequest] = useState(true)
|
||||
const [finished, setFinished] = useState(false)
|
||||
const [response, setResponse] = useState("")
|
||||
const [failed, setFailed] = useState(false)
|
||||
|
||||
if (firstRequest) {
|
||||
setFirstRequest(false);
|
||||
setFirstRequest(false)
|
||||
|
||||
//code
|
||||
//session_state
|
||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||
const params = Object.fromEntries(urlSearchParams.entries());
|
||||
|
||||
const authenticationStore = [];
|
||||
const authenticationStore = []
|
||||
var appAuthData = {
|
||||
label: "",
|
||||
app: {
|
||||
name: "",
|
||||
id: "",
|
||||
app_version: "",
|
||||
"label": "",
|
||||
"app": {
|
||||
"name": "",
|
||||
"id": "",
|
||||
"app_version": "",
|
||||
},
|
||||
fields: [],
|
||||
type: "oauth2",
|
||||
};
|
||||
"fields": [],
|
||||
"type": "oauth2",
|
||||
}
|
||||
|
||||
if (window !== undefined && window !== null) {
|
||||
console.log(window.location);
|
||||
appAuthData.fields.push({
|
||||
key: "redirect_uri",
|
||||
value: window.location.origin + window.location.pathname,
|
||||
});
|
||||
console.log(window.location)
|
||||
appAuthData.fields.push({"key": "redirect_uri", "value": window.location.origin+window.location.pathname})
|
||||
}
|
||||
|
||||
if (params.code !== undefined && params.code !== null) {
|
||||
appAuthData.fields.push({ key: "code", value: params.code });
|
||||
appAuthData.fields.push({"key": "code", "value": params.code})
|
||||
}
|
||||
|
||||
if (params.session_state !== undefined && params.session_state !== null) {
|
||||
appAuthData.fields.push({
|
||||
key: "session_state",
|
||||
value: params.session_state,
|
||||
});
|
||||
appAuthData.fields.push({"key": "session_state", "value": params.session_state})
|
||||
}
|
||||
|
||||
if (params.state !== undefined && params.state !== null) {
|
||||
const paramsplit = params.state.split("&");
|
||||
console.log(paramsplit);
|
||||
const paramsplit = params.state.split("&")
|
||||
console.log(paramsplit)
|
||||
for (var key in paramsplit) {
|
||||
const query = paramsplit[key].split("=");
|
||||
console.log(query);
|
||||
const query = paramsplit[key].split("=")
|
||||
console.log(query)
|
||||
|
||||
if (query.length !== 2) {
|
||||
console.log("INVALID QUERY: ", query);
|
||||
continue;
|
||||
console.log("INVALID QUERY: ", query)
|
||||
continue
|
||||
}
|
||||
|
||||
if (query[0] === "workflow_id") {
|
||||
appAuthData.reference_workflow = query[1];
|
||||
appAuthData.reference_workflow = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "reference_action_id") {
|
||||
@@ -70,101 +64,92 @@ const SetAuthentication = (props) => {
|
||||
}
|
||||
|
||||
if (query[0] === "app_name") {
|
||||
appAuthData.app.name = query[1];
|
||||
appAuthData.label = "Oauth2 for " + query[1];
|
||||
appAuthData.app.name = query[1]
|
||||
appAuthData.label = "Oauth2 for "+query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "app_id") {
|
||||
appAuthData.app.id = query[1];
|
||||
appAuthData.app.id = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "app_version") {
|
||||
appAuthData.app.app_version = query[1];
|
||||
appAuthData.app.app_version = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "authentication_url") {
|
||||
appAuthData.fields.push({
|
||||
key: "authentication_url",
|
||||
value: query[1],
|
||||
});
|
||||
appAuthData.fields.push({"key": "authentication_url", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "scope") {
|
||||
appAuthData.fields.push({ key: "scope", value: query[1] });
|
||||
appAuthData.fields.push({"key": "scope", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "client_id") {
|
||||
appAuthData.fields.push({ key: "client_id", value: query[1] });
|
||||
appAuthData.fields.push({"key": "client_id", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "client_secret") {
|
||||
appAuthData.fields.push({ key: "client_secret", value: query[1] });
|
||||
appAuthData.fields.push({"key": "client_secret", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "oauth_url") {
|
||||
appAuthData.fields.push({ key: "oauth_url", value: query[1] });
|
||||
appAuthData.fields.push({"key": "oauth_url", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "refresh_uri") {
|
||||
appAuthData.fields.push({ key: "refresh_uri", value: query[1] });
|
||||
appAuthData.fields.push({"key": "refresh_uri", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "refresh_url") {
|
||||
appAuthData.fields.push({ key: "refresh_url", value: query[1] });
|
||||
appAuthData.fields.push({"key": "refresh_url", "value": query[1]})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(appAuthData);
|
||||
console.log(appAuthData)
|
||||
|
||||
fetch(globalUrl + "/api/v1/apps/authentication", {
|
||||
method: "PUT",
|
||||
fetch(globalUrl+"/api/v1/apps/authentication", {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
body: JSON.stringify(appAuthData),
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for oauth2 authentication");
|
||||
setFailed(true);
|
||||
console.log("Status not 200 for oauth2 authentication")
|
||||
setFailed(true)
|
||||
}
|
||||
|
||||
return response.json();
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
//setUserSettings(responseJson)
|
||||
console.log("Resp: ", responseJson);
|
||||
setFinished(true);
|
||||
setResponse(responseJson.reason);
|
||||
console.log("Resp: ", responseJson)
|
||||
setFinished(true)
|
||||
setResponse(responseJson.reason)
|
||||
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
}, 1000);
|
||||
window.close()
|
||||
}, 1000)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ width: 1000, margin: "auto", itemAlign: "center" }}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
style={{ marginLeft: "auto", marginRight: "auto", marginTop: 200 }}
|
||||
>
|
||||
{!finished ? (
|
||||
<CircularProgress />
|
||||
) : (
|
||||
"DONE WITH AUTH - this will close soon!!"
|
||||
)}
|
||||
<div style={{width: 1000, margin: "auto", itemAlign: "center",}}>
|
||||
<Typography variant="h6" style={{marginLeft: "auto", marginRight: "auto", marginTop: 200, }}>
|
||||
{!finished ? <CircularProgress /> : "DONE WITH AUTH - this will close soon!!"}
|
||||
<div />
|
||||
{failed ? "Failed setup. Error: " : ""} {response}
|
||||
</Typography>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default SetAuthentication;
|
||||
|
||||
@@ -1,68 +1,62 @@
|
||||
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
|
||||
import React, {useRef, useState, useEffect, useLayoutEffect} from 'react';
|
||||
|
||||
import { Typography, CircularProgress } from "@material-ui/core";
|
||||
import { Typography, CircularProgress } from '@material-ui/core';
|
||||
|
||||
const SetAuthentication = (props) => {
|
||||
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
|
||||
|
||||
const [firstRequest, setFirstRequest] = useState(true);
|
||||
const [finished, setFinished] = useState(false);
|
||||
const [response, setResponse] = useState("");
|
||||
const [failed, setFailed] = useState(false);
|
||||
const [firstRequest, setFirstRequest] = useState(true)
|
||||
const [finished, setFinished] = useState(false)
|
||||
const [response, setResponse] = useState("")
|
||||
const [failed, setFailed] = useState(false)
|
||||
|
||||
if (firstRequest) {
|
||||
setFirstRequest(false);
|
||||
setFirstRequest(false)
|
||||
|
||||
//code
|
||||
//session_state
|
||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||
const params = Object.fromEntries(urlSearchParams.entries());
|
||||
|
||||
const authenticationStore = [];
|
||||
const authenticationStore = []
|
||||
var appAuthData = {
|
||||
label: "",
|
||||
app: {
|
||||
name: "",
|
||||
id: "",
|
||||
app_version: "",
|
||||
"label": "",
|
||||
"app": {
|
||||
"name": "",
|
||||
"id": "",
|
||||
"app_version": "",
|
||||
},
|
||||
fields: [],
|
||||
type: "oauth2",
|
||||
};
|
||||
"fields": [],
|
||||
"type": "oauth2",
|
||||
}
|
||||
|
||||
if (window !== undefined && window !== null) {
|
||||
console.log(window.location);
|
||||
appAuthData.fields.push({
|
||||
key: "redirect_uri",
|
||||
value: window.location.origin + window.location.pathname,
|
||||
});
|
||||
console.log(window.location)
|
||||
appAuthData.fields.push({"key": "redirect_uri", "value": window.location.origin+window.location.pathname})
|
||||
}
|
||||
|
||||
if (params.code !== undefined && params.code !== null) {
|
||||
appAuthData.fields.push({ key: "code", value: params.code });
|
||||
appAuthData.fields.push({"key": "code", "value": params.code})
|
||||
}
|
||||
|
||||
if (params.session_state !== undefined && params.session_state !== null) {
|
||||
appAuthData.fields.push({
|
||||
key: "session_state",
|
||||
value: params.session_state,
|
||||
});
|
||||
appAuthData.fields.push({"key": "session_state", "value": params.session_state})
|
||||
}
|
||||
|
||||
if (params.state !== undefined && params.state !== null) {
|
||||
const paramsplit = params.state.split("&");
|
||||
console.log(paramsplit);
|
||||
const paramsplit = params.state.split("&")
|
||||
console.log(paramsplit)
|
||||
for (var key in paramsplit) {
|
||||
const query = paramsplit[key].split("=");
|
||||
console.log(query);
|
||||
const query = paramsplit[key].split("=")
|
||||
console.log(query)
|
||||
|
||||
if (query.length !== 2) {
|
||||
console.log("INVALID QUERY: ", query);
|
||||
continue;
|
||||
console.log("INVALID QUERY: ", query)
|
||||
continue
|
||||
}
|
||||
|
||||
if (query[0] === "workflow_id") {
|
||||
appAuthData.reference_workflow = query[1];
|
||||
appAuthData.reference_workflow = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "reference_action_id") {
|
||||
@@ -70,89 +64,80 @@ const SetAuthentication = (props) => {
|
||||
}
|
||||
|
||||
if (query[0] === "app_name") {
|
||||
appAuthData.app.name = query[1];
|
||||
appAuthData.label = "Oauth2 for " + query[1];
|
||||
appAuthData.app.name = query[1]
|
||||
appAuthData.label = "Oauth2 for "+query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "app_id") {
|
||||
appAuthData.app.id = query[1];
|
||||
appAuthData.app.id = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "app_version") {
|
||||
appAuthData.app.app_version = query[1];
|
||||
appAuthData.app.app_version = query[1]
|
||||
}
|
||||
|
||||
if (query[0] === "authentication_url") {
|
||||
appAuthData.fields.push({
|
||||
key: "authentication_url",
|
||||
value: query[1],
|
||||
});
|
||||
appAuthData.fields.push({"key": "authentication_url", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "scope") {
|
||||
appAuthData.fields.push({ key: "scope", value: query[1] });
|
||||
appAuthData.fields.push({"key": "scope", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "client_id") {
|
||||
appAuthData.fields.push({ key: "client_id", value: query[1] });
|
||||
appAuthData.fields.push({"key": "client_id", "value": query[1]})
|
||||
}
|
||||
|
||||
if (query[0] === "client_secret") {
|
||||
appAuthData.fields.push({ key: "client_secret", value: query[1] });
|
||||
appAuthData.fields.push({"key": "client_secret", "value": query[1]})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(appAuthData);
|
||||
console.log(appAuthData)
|
||||
|
||||
fetch(globalUrl + "/api/v1/apps/authentication", {
|
||||
method: "PUT",
|
||||
fetch(globalUrl+"/api/v1/apps/authentication", {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
body: JSON.stringify(appAuthData),
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for oauth2 authentication");
|
||||
setFailed(true);
|
||||
console.log("Status not 200 for oauth2 authentication")
|
||||
setFailed(true)
|
||||
}
|
||||
|
||||
return response.json();
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
//setUserSettings(responseJson)
|
||||
console.log("Resp: ", responseJson);
|
||||
setFinished(true);
|
||||
setResponse(responseJson.reason);
|
||||
console.log("Resp: ", responseJson)
|
||||
setFinished(true)
|
||||
setResponse(responseJson.reason)
|
||||
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
}, 1000);
|
||||
window.close()
|
||||
}, 1000)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ width: 1000, margin: "auto", itemAlign: "center" }}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
style={{ marginLeft: "auto", marginRight: "auto", marginTop: 200 }}
|
||||
>
|
||||
{!finished ? (
|
||||
<CircularProgress />
|
||||
) : (
|
||||
"DONE WITH AUTH - this will close soon!!"
|
||||
)}
|
||||
<div style={{width: 1000, margin: "auto", itemAlign: "center",}}>
|
||||
<Typography variant="h6" style={{marginLeft: "auto", marginRight: "auto", marginTop: 200, }}>
|
||||
{!finished ? <CircularProgress /> : "DONE WITH AUTH - this will close soon!!"}
|
||||
<div />
|
||||
{failed ? "Failed setup. Error: " : ""} {response}
|
||||
</Typography>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default SetAuthentication;
|
||||
|
||||
+273
-395
File diff suppressed because it is too large
Load Diff
+141
-162
@@ -1,26 +1,26 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect} from 'react';
|
||||
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import ButtonBase from "@material-ui/core/ButtonBase";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import List from "@material-ui/core/List";
|
||||
import ListItem from "@material-ui/core/ListItem";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import Select from "@material-ui/core/Select";
|
||||
import MenuItem from "@material-ui/core/MenuItem";
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import ButtonBase from '@material-ui/core/ButtonBase';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import List from '@material-ui/core/List';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Select from '@material-ui/core/Select';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import DialogActions from "@material-ui/core/DialogActions";
|
||||
import DialogContent from "@material-ui/core/DialogContent";
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
|
||||
import WebhookImage from "../assets/img/webhook.png";
|
||||
import KafkaImage from "../assets/img/kafka.png";
|
||||
import WebhookImage from '../assets/img/webhook.png';
|
||||
import KafkaImage from '../assets/img/kafka.png';
|
||||
|
||||
const Webhooks = (props) => {
|
||||
const { globalUrl, isLoaded } = props;
|
||||
const validtypes = ["webhook"];
|
||||
const validtypes = ["webhook"]
|
||||
|
||||
//const [hooks, setSchedules] = React.useState(hookdata);
|
||||
const [hooks, setHooks] = React.useState([]);
|
||||
@@ -33,83 +33,77 @@ const Webhooks = (props) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (firstrequest) {
|
||||
setFirstrequest(false);
|
||||
getAvailableHooks();
|
||||
setFirstrequest(false)
|
||||
getAvailableHooks()
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const newHook = () => {
|
||||
if (newHookName.length === 0) {
|
||||
setModalError("Missing name in modal");
|
||||
return;
|
||||
setModalError("Missing name in modal")
|
||||
return
|
||||
}
|
||||
|
||||
if (!validtypes.includes(newHookType)) {
|
||||
setModalError(
|
||||
newHookType + " is not a valid type. Try this: " + validtypes
|
||||
);
|
||||
setModalError(newHookType + " is not a valid type. Try this: "+validtypes)
|
||||
}
|
||||
|
||||
fetch(globalUrl + "/api/v1/hooks/new", {
|
||||
fetch(globalUrl+"/api/v1/hooks/new", {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
name: newHookName,
|
||||
description: newHookDescription,
|
||||
type: newHookType,
|
||||
}),
|
||||
headers: {"content-type": "application/json"},
|
||||
body: JSON.stringify({"name": newHookName, "description": newHookDescription, "type": newHookType}),
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
console.log(responseJson);
|
||||
setHooks([]);
|
||||
console.log(responseJson)
|
||||
setHooks([])
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const getAvailableHooks = () => {
|
||||
fetch(globalUrl + "/api/v1/hooks", {
|
||||
method: "GET",
|
||||
fetch(globalUrl+"/api/v1/hooks", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
setHooks(responseJson);
|
||||
setHooks(responseJson)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
// window.location.pathname = "/"
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const deleteHook = (id) => {
|
||||
if (id === undefined) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
fetch(globalUrl + "/api/v1/hooks/" + id + "/delete", {
|
||||
method: "DELETE",
|
||||
fetch(globalUrl+"/api/v1/hooks/"+id+"/delete", {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
setHooks([]);
|
||||
setHooks([])
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const bodyDivStyle = {
|
||||
marginLeft: "20px",
|
||||
@@ -117,118 +111,114 @@ const Webhooks = (props) => {
|
||||
width: "1350px",
|
||||
minWidth: "1350px",
|
||||
maxWidth: "1350px",
|
||||
};
|
||||
}
|
||||
|
||||
const hookApp = (app) => {
|
||||
// Might be more options, but should be webhook or MQ
|
||||
const appPicture =
|
||||
app.type === "webhook" ? (
|
||||
<img src={WebhookImage} alt="webhook" width="100px" height="100px" />
|
||||
) : (
|
||||
<img src={KafkaImage} alt="MQ" width="100px" height="100px" />
|
||||
);
|
||||
|
||||
return (
|
||||
<Grid container spacing={2} style={{ margin: "10px 10px 10px 10px" }}>
|
||||
<Grid item style={{ marginRight: "10px" }}>
|
||||
<ButtonBase>{appPicture}</ButtonBase>
|
||||
// Might be more options, but should be webhook or MQ
|
||||
const appPicture = app.type === "webhook" ?
|
||||
<img
|
||||
src={WebhookImage}
|
||||
alt="webhook"
|
||||
width="100px"
|
||||
height="100px"
|
||||
/>
|
||||
:
|
||||
<img
|
||||
src={KafkaImage}
|
||||
alt="MQ"
|
||||
width="100px"
|
||||
height="100px"
|
||||
/>
|
||||
|
||||
return(
|
||||
<Grid container spacing={2} style={{margin: "10px 10px 10px 10px"}}>
|
||||
<Grid item style={{marginRight: "10px"}}>
|
||||
<ButtonBase>
|
||||
{appPicture}
|
||||
</ButtonBase>
|
||||
</Grid>
|
||||
{splitter}
|
||||
<Grid item xs={12} sm container style={{ marginLeft: "10px" }}>
|
||||
<Grid item xs={12} sm container style={{marginLeft: "10px"}}>
|
||||
<Grid item xs container direction="column" spacing={2}>
|
||||
<Grid item xs>
|
||||
<div>
|
||||
<h2>{app.info.name}</h2>
|
||||
</div>
|
||||
<div>Desc: {app.info.description}</div>
|
||||
<div>Status: {app.status}</div>
|
||||
<div>
|
||||
Desc: {app.info.description}
|
||||
</div>
|
||||
<div>
|
||||
Status: {app.status}
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item>{app.action}</Grid>
|
||||
<Grid item>
|
||||
{app.action}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
const splitter = (
|
||||
<div
|
||||
style={{
|
||||
width: "1px",
|
||||
backgroundColor: "grey",
|
||||
margin: "5px 5px 5px 5px",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const splitter = <div style={{width: "1px", backgroundColor: "grey", margin:"5px 5px 5px 5px"}} />
|
||||
|
||||
const hrefStyle = {
|
||||
color: "#385f71",
|
||||
textDecoration: "none",
|
||||
};
|
||||
textDecoration: "none"
|
||||
}
|
||||
|
||||
// FIXME - add Schedule modal
|
||||
const hookPaper = (hook) => {
|
||||
return (
|
||||
return(
|
||||
<div>
|
||||
<Paper
|
||||
style={{
|
||||
maxWidth: "500px",
|
||||
display: "flex",
|
||||
padding: "10px 10px 10px 10px",
|
||||
marginTop: "10px",
|
||||
}}
|
||||
>
|
||||
<div style={{ flex: "5" }}>{hookApp(hook)}</div>
|
||||
<Paper style={{maxWidth: "500px", display: "flex", padding: "10px 10px 10px 10px", marginTop: "10px"}}>
|
||||
<div style={{flex: "5"}}>
|
||||
{hookApp(hook)}
|
||||
</div>
|
||||
{splitter}
|
||||
<div style={{ flex: "1" }}>
|
||||
<List style={{ backgroundColor: "#ffffff" }}>
|
||||
<ListItem style={{ flex: "1", textAlign: "center" }}>
|
||||
<a href={"/webhooks/" + hook.id} style={hrefStyle}>
|
||||
<Button disabled={false} color="primary">
|
||||
<div style={{flex: "1"}}>
|
||||
<List style={{backgroundColor: "#ffffff"}}>
|
||||
<ListItem style={{flex: "1", textAlign: "center"}}>
|
||||
<a href={"/webhooks/"+hook.id} style={hrefStyle} >
|
||||
<Button
|
||||
disabled={false}
|
||||
color="primary"
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</a>
|
||||
</ListItem>
|
||||
<ListItem style={{ flex: "1", textAlign: "center" }}>
|
||||
<ListItem style={{flex: "1", textAlign: "center"}}>
|
||||
<Button
|
||||
disabled={false}
|
||||
onClick={() => {
|
||||
deleteHook(hook.id);
|
||||
}}
|
||||
onClick={() => {deleteHook(hook.id)}}
|
||||
color="primary"
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
>Delete</Button>
|
||||
</ListItem>
|
||||
</List>
|
||||
</div>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const modalView = modalOpen ? (
|
||||
<Dialog
|
||||
modal
|
||||
const modalView = modalOpen ?
|
||||
<Dialog modal
|
||||
open={modalOpen}
|
||||
onClose={() => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
onClose={() => {setModalOpen(false)}}
|
||||
>
|
||||
<DialogTitle>Hook configuration</DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
onChange={(event) => {
|
||||
setNewHookName(event.target.value);
|
||||
}}
|
||||
onChange={(event) => {setNewHookName(event.target.value)}}
|
||||
color="primary"
|
||||
placeholder="Name"
|
||||
margin="dense"
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
onChange={(event) => {
|
||||
setNewHookDescription(event.target.value);
|
||||
}}
|
||||
onChange={(event) => {setNewHookDescription(event.target.value)}}
|
||||
color="primary"
|
||||
placeholder="Description"
|
||||
margin="dense"
|
||||
@@ -237,13 +227,13 @@ const Webhooks = (props) => {
|
||||
|
||||
<Select
|
||||
value={newHookType}
|
||||
onChange={(event) => {
|
||||
setNewHookType(event.target.value);
|
||||
}}
|
||||
onChange={(event) => {setNewHookType(event.target.value)}}
|
||||
fullWidth="true"
|
||||
>
|
||||
{validtypes.map((data) => (
|
||||
<MenuItem value={data}>{data}</MenuItem>
|
||||
{validtypes.map(data => (
|
||||
<MenuItem value={data}>
|
||||
{data}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</DialogContent>
|
||||
@@ -251,66 +241,55 @@ const Webhooks = (props) => {
|
||||
<Button onClick={() => setModalOpen(false)} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
newHookName.length === 0 || !validtypes.includes(newHookType)
|
||||
}
|
||||
onClick={() => {
|
||||
newHook();
|
||||
setModalOpen(false);
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
<Button disabled={newHookName.length === 0 || !validtypes.includes(newHookType)} onClick={() => {newHook(); setModalOpen(false)}} color="primary">
|
||||
Submit
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
) : null;
|
||||
: null
|
||||
|
||||
const hookmap =
|
||||
hooks.length > 0 ? (
|
||||
<div>{hooks.map((data) => hookPaper(data))}</div>
|
||||
) : (
|
||||
<div style={{ marginTop: "10%", marginLeft: "50%" }}>
|
||||
const hookmap = hooks.length > 0 ?
|
||||
<div>
|
||||
{hooks.map(data => (
|
||||
hookPaper(data)
|
||||
))}
|
||||
</div>
|
||||
:
|
||||
<div style={{marginTop: "10%", marginLeft: "50%"}} >
|
||||
<Button
|
||||
disabled={false}
|
||||
onClick={() => {
|
||||
setModalOpen(true);
|
||||
}}
|
||||
onClick={() => {setModalOpen(true)}}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
>
|
||||
CREATE NEW HOOK
|
||||
</Button>
|
||||
>CREATE NEW HOOK</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
const hookView = (
|
||||
const hookView =
|
||||
<div style={bodyDivStyle}>
|
||||
<Button
|
||||
disabled={false}
|
||||
onClick={() => {
|
||||
setModalOpen(true);
|
||||
}}
|
||||
onClick={() => {setModalOpen(true)}}
|
||||
color="primary"
|
||||
>
|
||||
New
|
||||
</Button>
|
||||
>New</Button>
|
||||
{hookmap}
|
||||
</div>
|
||||
);
|
||||
|
||||
const loadedCheck = isLoaded ? (
|
||||
const loadedCheck = isLoaded ?
|
||||
<div>
|
||||
{modalView}
|
||||
{hookView}
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
);
|
||||
:
|
||||
<div>
|
||||
</div>
|
||||
|
||||
|
||||
// Maybe use gridview or something, idk
|
||||
return <div>{loadedCheck}</div>;
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
{loadedCheck}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Webhooks;
|
||||
export default Webhooks
|
||||
|
||||
+958
-1628
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user