Merge pull request #108 from frikky/1.0.0

0.6.1
This commit is contained in:
Frikky
2020-07-27 20:05:08 +09:00
committed by GitHub
50 changed files with 987 additions and 898 deletions
+13 -3
View File
@@ -101,7 +101,7 @@ class AppBase:
except requests.exceptions.ConnectionError as e: except requests.exceptions.ConnectionError as e:
print("Connectionerror: %s" % e) print("Connectionerror: %s" % e)
action_result["result"] = "Bad setup during startup: %d" % e action_result["result"] = "Bad setup during startup: %s" % e
self.send_result(action_result, headers, stream_path) self.send_result(action_result, headers, stream_path)
return return
@@ -288,7 +288,7 @@ class AppBase:
# Do stuff here. # Do stuff here.
innervalue = parse_nested_param(data, maxDepth(data)-0) innervalue = parse_nested_param(data, maxDepth(data)-0)
outervalue = parse_nested_param(data, maxDepth(data)-1) outervalue = parse_nested_param(data, maxDepth(data)-1)
print("INNER: ", outervalue) print("INNER: ", innervalue)
print("OUTER: ", outervalue) print("OUTER: ", outervalue)
if outervalue != innervalue: if outervalue != innervalue:
@@ -710,7 +710,17 @@ class AppBase:
continue continue
#print(destinationvalue) #print(destinationvalue)
if not run_validation(sourcevalue, condition["condition"]["value"], destinationvalue): # NEGATE
validation = run_validation(sourcevalue, condition["condition"]["value"], destinationvalue)
# Configuration = negated because of WorkflowAppActionParam..
try:
if condition["condition"]["configuration"]:
validation = not validation
except KeyError:
pass
if not validation:
self.logger.info("Failed condition check for %s %s %s." % (sourcevalue, condition["condition"]["value"], destinationvalue)) self.logger.info("Failed condition check for %s %s %s." % (sourcevalue, condition["condition"]["value"], destinationvalue))
return False, "Failed condition: %s %s %s" % (sourcevalue, condition["condition"]["value"], destinationvalue) return False, "Failed condition: %s %s %s" % (sourcevalue, condition["condition"]["value"], destinationvalue)
+1 -1
View File
@@ -398,7 +398,7 @@ func makePythoncode(swagger *openapi3.Swagger, name, url, method string, paramet
verifyAddin, verifyAddin,
) )
log.Printf("%s", data) //log.Printf("%s", data)
return functionname, data return functionname, data
} }
+14 -4
View File
@@ -662,7 +662,7 @@ func handleApiAuthentication(resp http.ResponseWriter, request *http.Request) (U
if len(Userdata.Username) > 0 { if len(Userdata.Username) > 0 {
return Userdata, nil return Userdata, nil
} else { } else {
return Userdata, errors.New("User is invalid") return Userdata, errors.New(fmt.Sprintf("User is invalid - no username found: %#v", Userdata))
} }
} }
@@ -1605,8 +1605,11 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) {
} }
// This is a long check to see if an inactive admin can access the site // This is a long check to see if an inactive admin can access the site
parsedAdmin := "false"
if !userInfo.Active { if !userInfo.Active {
if userInfo.Role == "admin" { if userInfo.Role == "admin" {
parsedAdmin = "true"
ctx := context.Background() ctx := context.Background()
q := datastore.NewQuery("Users") q := datastore.NewQuery("Users")
var users []User var users []User
@@ -1672,7 +1675,14 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) {
Expires: expiration, Expires: expiration,
}) })
returnData := fmt.Sprintf(`{"success": true, "cookies": [{"key": "session_token", "value": "%s", "expiration": %d}]}`, userInfo.Session, expiration.Unix()) returnData := fmt.Sprintf(`
{
"success": true,
"admin": %s,
"orgs": [{"name": "Shuffle", "id": "123", "role": "admin"}],
"selected_org": {"name": "Shuffle", "id": "123", "role": "admin"},
"cookies": [{"key": "session_token", "value": "%s", "expiration": %d}]
}`, parsedAdmin, userInfo.Session, expiration.Unix())
resp.WriteHeader(200) resp.WriteHeader(200)
resp.Write([]byte(returnData)) resp.Write([]byte(returnData))
@@ -6134,7 +6144,7 @@ func handleAppHotload(location string) error {
} }
//log.Printf("Reading app folder: %#v", dir) //log.Printf("Reading app folder: %#v", dir)
err = iterateAppGithubFolders(fs, dir, "", "") err = iterateAppGithubFolders(fs, dir, "", "", false)
if err != nil { if err != nil {
log.Printf("Err: %s", err) log.Printf("Err: %s", err)
return err return err
@@ -6345,7 +6355,7 @@ func runInit(ctx context.Context) {
//iterateAppGithubFolders(fs, dir, "", "testing") //iterateAppGithubFolders(fs, dir, "", "testing")
// FIXME: Get all the apps? // FIXME: Get all the apps?
iterateAppGithubFolders(fs, dir, "", "") iterateAppGithubFolders(fs, dir, "", "", false)
// Hotloads locally // Hotloads locally
location := os.Getenv("APP_HOTLOAD_FOLDER") location := os.Getenv("APP_HOTLOAD_FOLDER")
+22 -8
View File
@@ -94,6 +94,7 @@ type AuthenticationUsage struct {
} }
// An app inside Shuffle // An app inside Shuffle
// Source string `json:"source" datastore:"soure" yaml:"source"` - downloadlocation
type WorkflowApp struct { type WorkflowApp struct {
Name string `json:"name" yaml:"name" required:true datastore:"name"` Name string `json:"name" yaml:"name" required:true datastore:"name"`
IsValid bool `json:"is_valid" yaml:"is_valid" required:true datastore:"is_valid"` IsValid bool `json:"is_valid" yaml:"is_valid" required:true datastore:"is_valid"`
@@ -4224,6 +4225,7 @@ func loadSpecificApps(resp http.ResponseWriter, request *http.Request) {
URL string `json:"url"` URL string `json:"url"`
Field1 string `json:"field_1"` Field1 string `json:"field_1"`
Field2 string `json:"field_2"` Field2 string `json:"field_2"`
ForceUpdate bool `json:"force_update"`
} }
//log.Printf("Body: %s", string(body)) //log.Printf("Body: %s", string(body))
@@ -4265,7 +4267,13 @@ func loadSpecificApps(resp http.ResponseWriter, request *http.Request) {
log.Printf("FAiled reading folder: %s", err) log.Printf("FAiled reading folder: %s", err)
} }
_ = r _ = r
iterateAppGithubFolders(fs, dir, "", "")
if tmpBody.ForceUpdate {
log.Printf("Running with force update!")
} else {
log.Printf("Updating apps with updates")
}
iterateAppGithubFolders(fs, dir, "", "", tmpBody.ForceUpdate)
} else if strings.Contains(tmpBody.URL, "s3") { } else if strings.Contains(tmpBody.URL, "s3") {
//https://docs.aws.amazon.com/sdk-for-go/api/service/s3/ //https://docs.aws.amazon.com/sdk-for-go/api/service/s3/
@@ -4490,8 +4498,13 @@ func iterateWorkflowGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra
} }
// Onlyname is used to // Onlyname is used to
func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra string, onlyname string) error { func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra string, onlyname string, forceUpdate bool) error {
var err error var err error
allapps := []WorkflowApp{}
// It's here to prevent getting them in every iteration
ctx := context.Background()
for _, file := range dir { for _, file := range dir {
if len(onlyname) > 0 && file.Name() != onlyname { if len(onlyname) > 0 && file.Name() != onlyname {
continue continue
@@ -4508,7 +4521,7 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
} }
// Go routine? Hmm, this can be super quick I guess // Go routine? Hmm, this can be super quick I guess
err = iterateAppGithubFolders(fs, dir, tmpExtra, "") err = iterateAppGithubFolders(fs, dir, tmpExtra, "", forceUpdate)
if err != nil { if err != nil {
log.Printf("Error reading folder: %s", err) log.Printf("Error reading folder: %s", err)
continue continue
@@ -4591,12 +4604,12 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
fmt.Sprintf("%s:%s_%s", baseDockerName, newName, workflowapp.AppVersion), fmt.Sprintf("%s:%s_%s", baseDockerName, newName, workflowapp.AppVersion),
} }
ctx := context.Background() if len(allapps) == 0 {
allapps, err := getAllWorkflowApps(ctx) allapps, err = getAllWorkflowApps(ctx)
if err != nil { if err != nil {
log.Printf("Failed getting apps to verify: %s", err) log.Printf("Failed getting apps to verify: %s", err)
continue continue
//return err }
} }
// Make an option to override existing apps? // Make an option to override existing apps?
@@ -4607,7 +4620,7 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
if app.Name == workflowapp.Name && app.AppVersion == workflowapp.AppVersion { if app.Name == workflowapp.Name && app.AppVersion == workflowapp.AppVersion {
// FIXME: Check if there's a new APP_SDK as well. // FIXME: Check if there's a new APP_SDK as well.
// Skip this check if app_sdk is new. // Skip this check if app_sdk is new.
if app.Hash == md5 && app.Hash != "" { if app.Hash == md5 && app.Hash != "" && !forceUpdate {
skip = true skip = true
break break
} }
@@ -4617,7 +4630,7 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
} }
} }
if skip { if skip && !forceUpdate {
continue continue
} }
@@ -4677,6 +4690,7 @@ func iterateAppGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra strin
if len(removeApps) > 0 { if len(removeApps) > 0 {
for _, item := range removeApps { for _, item := range removeApps {
log.Printf("Removing duplicate: %s", item)
err = DeleteKey(ctx, "workflowapp", item) err = DeleteKey(ctx, "workflowapp", item)
if err != nil { if err != nil {
log.Printf("Failed deleting %s", item) log.Printf("Failed deleting %s", item)
+13 -13
View File
@@ -1,6 +1,6 @@
{ {
"name": "shuffler", "name": "shuffler",
"version": "0.3.0", "version": "0.6.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@@ -3733,9 +3733,9 @@
"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA=="
}, },
"@types/node": { "@types/node": {
"version": "14.0.13", "version": "14.0.24",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.24.tgz",
"integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==" "integrity": "sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA=="
}, },
"@types/object-assign": { "@types/object-assign": {
"version": "4.0.30", "version": "4.0.30",
@@ -3748,9 +3748,9 @@
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
}, },
"@types/prop-types": { "@types/prop-types": {
"version": "15.7.1", "version": "15.7.3",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
"integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==" "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
}, },
"@types/q": { "@types/q": {
"version": "1.5.4", "version": "1.5.4",
@@ -3758,9 +3758,9 @@
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
}, },
"@types/react": { "@types/react": {
"version": "16.8.20", "version": "16.9.43",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.20.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.43.tgz",
"integrity": "sha512-ZLmI+ubSJpfUIlQuULDDrdyuFQORBuGOvNnMue8HeA0GVrAJbWtZQhcBvnBPNRBI/GrfSfrKPFhthzC2SLEtLQ==", "integrity": "sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg==",
"requires": { "requires": {
"@types/prop-types": "*", "@types/prop-types": "*",
"csstype": "^2.2.0" "csstype": "^2.2.0"
@@ -11944,9 +11944,9 @@
} }
}, },
"lodash": { "lodash": {
"version": "4.17.15", "version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
}, },
"lodash._reinterpolate": { "lodash._reinterpolate": {
"version": "3.0.0", "version": "3.0.0",
-169
View File
@@ -1,169 +0,0 @@
import React, {useState, useEffect} from 'react';
import {Route} from 'react-router';
import {BrowserRouter} from 'react-router-dom';
import { CookiesProvider } from 'react-cookie';
import { useCookies } from 'react-cookie';
import EditSchedule from "./EditSchedule";
import Schedules from "./Schedules";
import Webhooks from "./Webhooks";
import Workflows from "./Workflows";
import EditWebhook from "./EditWebhook";
import AngularWorkflow from "./AngularWorkflow";
import ForgotPassword from "./ForgotPassword";
import ForgotPasswordLink from "./ForgotPasswordLink";
import Header from './Header';
import Apps from './Apps';
import AppCreator from './AppCreator';
import Contact from './Contact';
import Oauth2 from './Oauth2';
import About from "./About";
import Post from "./Post";
import Dashboard from "./Dashboard";
import AdminSetup from "./AdminSetup";
import Admin from "./Admin";
import Docs from "./Docs";
import RegisterLink from "./RegisterLink";
import LandingPage from "./Landingpage";
import LandingPageNew from "./LandingpageNew";
import LoginPage from "./LoginPage";
import SettingsPage from "./SettingsPage";
import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider';
import { createMuiTheme } from '@material-ui/core/styles';
import AlertTemplate from "react-alert-template-basic";
import { positions, Provider } from "react-alert";
// Production - backend proxy forwarding in nginx
var globalUrl = window.location.origin
// CORS used for testing purposes. Should only happen with specific port and http
if (window.location.protocol == "http:" && window.location.port === "3000") {
globalUrl = "http://localhost:5001"
}
const surfaceColor = "#27292D"
const inputColor = "#383B40"
const theme = createMuiTheme({
palette: {
primary: {
main: "#f85a3e"
},
secondary: {
main: '#e8eaf6',
},
},
typography: {
useNextVariants: true
},
overrides: {
MuiMenu: {
list: {
backgroundColor: inputColor,
},
},
},
});
// FIXME - set client side cookies
const App = (message, props) => {
const [userdata, setUserData] = useState({});
//const [homePage, ] = useState(true);
const [cookies, setCookie, removeCookie] = useCookies([]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [dataset, setDataset] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => {
if (dataset === false) {
checkLogin()
setDataset(true)
}})
if (isLoaded && !isLoggedIn && (!window.location.pathname.startsWith("/login") && (!window.location.pathname.startsWith("/docs") && (!window.location.pathname.startsWith("/adminsetup"))))) {
window.location = "/login"
}
const checkLogin = () => {
var baseurl = globalUrl
fetch(baseurl+"/api/v1/users/getinfo", {
credentials: "include",
headers: {
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(responseJson => {
if (responseJson.success === true) {
setUserData(responseJson)
setIsLoggedIn(true)
// Updating cookie every request
for (var key in responseJson["cookies"]) {
setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, {path: "/"})
}
}
setIsLoaded(true)
})
.catch(error => {
setIsLoaded(true)
});
}
// Dumb for content load (per now), but good for making the site not suddenly reload parts (ajax thingies)
const options = {
timeout: 5000,
position: positions.BOTTOM_CENTER
};
const includedData = window.location.pathname === "/home" || window.location.pathname === "/features" ?
<div>
<Route exact path="/home" render={props => <LandingPageNew isLoaded={isLoaded} {...props} /> } />
</div> :
<div style={{backgroundColor: "#1F2023", color: "rgba(255, 255, 255, 0.65)", minHeight: "100vh"}}>
<Header removeCookie={removeCookie} isLoaded={isLoaded} globalUrl={globalUrl} setIsLoggedIn={setIsLoggedIn} isLoggedIn={isLoggedIn} surfaceColor={surfaceColor} inputColor={inputColor}{...props} />
<Route exact path="/oauth2" render={props => <Oauth2 isLoaded={isLoaded} globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor}{...props} /> } />
<Route exact path="/contact" render={props => <Contact isLoaded={isLoaded} globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/login" render={props => <LoginPage isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/admin" render={props => <Admin isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/settings" render={props => <SettingsPage isLoaded={isLoaded} userdata={userdata} globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/AdminSetup" render={props => <AdminSetup isLoaded={isLoaded} userdata={userdata} globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor} {...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} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/schedules" render={props => <Schedules globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/dashboard" render={props => <Dashboard isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/apps" render={props => <Apps isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/apps/new" render={props => <AppCreator isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/apps/edit/:appid" render={props => <AppCreator isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/schedules/:key" render={props => <EditSchedule globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor} {...props} /> } />
<Route exact path="/workflows" render={props => <Workflows isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} cookies={cookies} surfaceColor={surfaceColor} inputColor={inputColor}{...props} /> } />
<Route exact path="/workflows/:key" render={props => <AngularWorkflow globalUrl={globalUrl} isLoaded={isLoaded} isLoggedIn={isLoggedIn} surfaceColor={surfaceColor} inputColor={inputColor}{...props} /> } />
<Route exact path="/docs/:key" render={props => <Docs isLoaded={isLoaded} globalUrl={globalUrl} surfaceColor={surfaceColor} inputColor={inputColor}{...props} /> } />
<Route exact path="/docs" render={props => {window.location.pathname = "/docs/about"}} />
<Route exact path="/" render={props => {window.location.pathname = "/login"}} />
</div>
// <div style={{backgroundColor: "rgba(21, 32, 43, 1)", color: "#fffff", minHeight: "100vh"}}>
// backgroundColor: "#213243",
// This is a mess hahahah
return (
<MuiThemeProvider theme={theme}>
<CookiesProvider>
<BrowserRouter>
<Provider template={AlertTemplate} {...options}>
{includedData}
</Provider>
</BrowserRouter>
</CookiesProvider>
</MuiThemeProvider>
);
};
export default App;
+163
View File
@@ -0,0 +1,163 @@
import React, { useState, useEffect } from 'react';
import { Route } from 'react-router';
import { BrowserRouter } from 'react-router-dom';
import { CookiesProvider } from 'react-cookie';
import { useCookies } from 'react-cookie';
import EditSchedule from "./views/EditSchedule";
import Schedules from "./views/Schedules";
import Webhooks from "./views/Webhooks";
import Workflows from "./views/Workflows";
import EditWebhook from "./views/EditWebhook";
import AngularWorkflow from "./views/AngularWorkflow";
import Header from './components/Header';
import Apps from './views/Apps';
import AppCreator from './views/AppCreator';
import Contact from './views/Contact';
import Oauth2 from './views/Oauth2';
import Dashboard from "./views/Dashboard";
import AdminSetup from "./views/AdminSetup";
import Admin from "./views/Admin";
import Docs from "./views/Docs";
import LandingPageNew from "./views/LandingpageNew";
import LoginPage from "./views/LoginPage";
import SettingsPage from "./views/SettingsPage";
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles';
import AlertTemplate from "react-alert-template-basic";
import { positions, Provider } from "react-alert";
// Production - backend proxy forwarding in nginx
var globalUrl = window.location.origin
// CORS used for testing purposes. Should only happen with specific port and http
if (window.location.protocol == "http:" && window.location.port === "3000") {
globalUrl = "http://localhost:5001"
}
const theme = createMuiTheme({
palette: {
primary: {
main: "#f85a3e"
},
secondary: {
main: '#e8eaf6',
},
surfaceColor: "#27292d",
inputColor: "#383B40"
},
typography: {
useNextVariants: true
},
overrides: {
MuiMenu: {
list: {
backgroundColor: "#383B40",
},
},
},
});
// FIXME - set client side cookies
const App = (message, props) => {
const [userdata, setUserData] = useState({});
//const [homePage, ] = useState(true);
const [cookies, setCookie, removeCookie] = useCookies([]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [dataset, setDataset] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => {
if (dataset === false) {
checkLogin()
setDataset(true)
}
})
if (isLoaded && !isLoggedIn && (!window.location.pathname.startsWith("/login") && (!window.location.pathname.startsWith("/docs") && (!window.location.pathname.startsWith("/adminsetup"))))) {
window.location = "/login"
}
const checkLogin = () => {
var baseurl = globalUrl
fetch(baseurl + "/api/v1/users/getinfo", {
credentials: "include",
headers: {
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(responseJson => {
if (responseJson.success === true) {
setUserData(responseJson)
setIsLoggedIn(true)
// Updating cookie every request
for (var key in responseJson["cookies"]) {
setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, { path: "/" })
}
}
setIsLoaded(true)
})
.catch(error => {
setIsLoaded(true)
});
}
// Dumb for content load (per now), but good for making the site not suddenly reload parts (ajax thingies)
const options = {
timeout: 5000,
position: positions.BOTTOM_CENTER
};
const includedData = window.location.pathname === "/home" || window.location.pathname === "/features" ?
<div>
<Route exact path="/home" render={props => <LandingPageNew isLoaded={isLoaded} {...props} />} />
</div> :
<div style={{ backgroundColor: "#1F2023", color: "rgba(255, 255, 255, 0.65)", minHeight: "100vh" }}>
<Header removeCookie={removeCookie} isLoaded={isLoaded} globalUrl={globalUrl} setIsLoggedIn={setIsLoggedIn} isLoggedIn={isLoggedIn} userdata={userdata} {...props} />
<Route exact path="/oauth2" render={props => <Oauth2 isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
<Route exact path="/contact" render={props => <Contact isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
<Route exact path="/login" render={props => <LoginPage isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
<Route exact path="/admin" render={props => <Admin isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
<Route exact path="/settings" render={props => <SettingsPage isLoaded={isLoaded} userdata={userdata} globalUrl={globalUrl} {...props} />} />
<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" render={props => <Apps 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/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 isLoaded={isLoaded} isLoggedIn={isLoggedIn} globalUrl={globalUrl} cookies={cookies} {...props} />} />
<Route exact path="/workflows/:key" render={props => <AngularWorkflow globalUrl={globalUrl} isLoaded={isLoaded} isLoggedIn={isLoggedIn} {...props} />} />
<Route exact path="/docs/:key" render={props => <Docs isLoaded={isLoaded} globalUrl={globalUrl} {...props} />} />
<Route exact path="/docs" render={props => { window.location.pathname = "/docs/about" }} />
<Route exact path="/" render={props => { window.location.pathname = "/login" }} />
</div>
// <div style={{backgroundColor: "rgba(21, 32, 43, 1)", color: "#fffff", minHeight: "100vh"}}>
// backgroundColor: "#213243",
// This is a mess hahahah
return (
<MuiThemeProvider theme={theme}>
<CookiesProvider>
<BrowserRouter>
<Provider template={AlertTemplate} {...options}>
{includedData}
</Provider>
</BrowserRouter>
</CookiesProvider>
</MuiThemeProvider>
);
};
export default App;
-25
View File
@@ -1,25 +0,0 @@
import React from 'react';
const Flows = () => {
return (
<div>
<h1>Flows</h1>
<p>
Built to suit any organization
</p>
<p>
WAT
</p>
<p>
</p>
<p></p>
</div>
)
}
export default Flows;
-25
View File
@@ -1,25 +0,0 @@
import React from 'react';
const Hooks = () => {
return (
<div>
<h1>Hooks</h1>
<p>
Built to suit any organization
</p>
<p>
WAT
</p>
<p>
</p>
<p></p>
</div>
)
}
export default Hooks;
-25
View File
@@ -1,25 +0,0 @@
import React from 'react';
const Schedules = () => {
return (
<div>
<h1>Schedules</h1>
<p>
Built to suit any organization
</p>
<p>
WAT
</p>
<p>
</p>
<p></p>
</div>
)
}
export default Schedules;
@@ -5,19 +5,22 @@ import {Link} from 'react-router-dom';
import List from '@material-ui/core/List'; import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem'; import ListItem from '@material-ui/core/ListItem';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import HomeIcon from '@material-ui/icons/Home'; import HomeIcon from '@material-ui/icons/Home';
import PolymerIcon from '@material-ui/icons/Polymer'; import PolymerIcon from '@material-ui/icons/Polymer';
import AppsIcon from '@material-ui/icons/Apps'; import AppsIcon from '@material-ui/icons/Apps';
import DescriptionIcon from '@material-ui/icons/Description'; import DescriptionIcon from '@material-ui/icons/Description';
import Grid from '@material-ui/core/Grid'; import Grid from '@material-ui/core/Grid';
import { useTheme } from '@material-ui/core/styles';
const hoverColor = "#f85a3e" const hoverColor = "#f85a3e"
const hoverOutColor = "#e8eaf6" const hoverOutColor = "#e8eaf6"
const Header = props => { const Header = props => {
const { globalUrl, isLoggedIn, removeCookie, homePage, isLoaded } = props; const { globalUrl, isLoggedIn, removeCookie, homePage, isLoaded, userdata } = props;
const theme = useTheme();
const [HomeHoverColor, setHomeHoverColor] = useState(hoverOutColor); const [HomeHoverColor, setHomeHoverColor] = useState(hoverOutColor);
const [SoarHoverColor, setSoarHoverColor] = useState(hoverOutColor); const [SoarHoverColor, setSoarHoverColor] = useState(hoverOutColor);
@@ -192,6 +195,32 @@ const Header = props => {
</Button> </Button>
</Link> </Link>
</ListItem> </ListItem>
{userdata === undefined || userdata.orgs.length <= 1 ? null :
<ListItem>
<Select
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
value={userdata.selected_org}
fullWidth
style={{backgroundColor: theme.palette.surfaceColor, color: "white", height: "50px"}}
onChange={(e) => {
console.log("SET ORG TO ", e.target.value)
}}
>
{userdata.orgs.map(data => {
return (
<MenuItem key={data.id} style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={data}>
{data.name}
</MenuItem>
)
})}
</Select>
</ListItem>
}
</List> </List>
</div> </div>
</div> </div>
@@ -287,7 +316,7 @@ const Header = props => {
<div> <div>
{loadedCheck} {loadedCheck}
</div> </div>
); )
}; }
export default Header; export default Header;
@@ -2,6 +2,8 @@ import React, { useEffect} from 'react';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Switch from '@material-ui/core/Switch';
import Select from '@material-ui/core/Select'; import Select from '@material-ui/core/Select';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import List from '@material-ui/core/List'; import List from '@material-ui/core/List';
@@ -16,17 +18,21 @@ import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
import { useAlert } from "react-alert"; import { useAlert } from "react-alert";
import Dialog from '@material-ui/core/Dialog'; import { Dialog, DialogTitle, DialogActions, DialogContent } from '@material-ui/core';
import DialogTitle from '@material-ui/core/DialogTitle'; import { useTheme } from '@material-ui/core/styles';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import CachedIcon from '@material-ui/icons/Cached'; import CachedIcon from '@material-ui/icons/Cached';
import AccessibilityNewIcon from '@material-ui/icons/AccessibilityNew';
import LockIcon from '@material-ui/icons/Lock';
import EcoIcon from '@material-ui/icons/Eco';
import ScheduleIcon from '@material-ui/icons/Schedule';
import CloudIcon from '@material-ui/icons/Cloud';
import BusinessIcon from '@material-ui/icons/Business';
const surfaceColor = "#27292D"
const inputColor = "#383B40"
const Admin = (props) => { const Admin = (props) => {
const { globalUrl, } = props; const { globalUrl } = props;
const theme = useTheme();
const [firstRequest, setFirstRequest] = React.useState(true); const [firstRequest, setFirstRequest] = React.useState(true);
const [modalUser, setModalUser] = React.useState({}); const [modalUser, setModalUser] = React.useState({});
const [modalOpen, setModalOpen] = React.useState(false); const [modalOpen, setModalOpen] = React.useState(false);
@@ -45,10 +51,10 @@ const Admin = (props) => {
const alert = useAlert() const alert = useAlert()
const deleteAuthentication = (data) => { const deleteAuthentication = (data) => {
alert.info("Deleting auth "+data.label) alert.info("Deleting auth " + data.label)
// Just use this one? // Just use this one?
const url = globalUrl+'/api/v1/apps/authentication/'+data.id const url = globalUrl + '/api/v1/apps/authentication/' + data.id
console.log("URL: ", url) console.log("URL: ", url)
fetch(url, { fetch(url, {
method: 'DELETE', method: 'DELETE',
@@ -78,7 +84,7 @@ const Admin = (props) => {
console.log("INPUT: ", data) console.log("INPUT: ", data)
// Just use this one? // Just use this one?
const url = globalUrl+'/api/v1/workflows/'+data["workflow_id"]+"/schedule/"+data.id const url = globalUrl + '/api/v1/workflows/' + data["workflow_id"] + "/schedule/" + data.id
console.log("URL: ", url) console.log("URL: ", url)
fetch(url, { fetch(url, {
method: 'DELETE', method: 'DELETE',
@@ -104,8 +110,9 @@ const Admin = (props) => {
} }
const onPasswordChange = () => { const onPasswordChange = () => {
const data = {"username": selectedUser.username, "newpassword": newPassword} const data = { "username": selectedUser.username, "newpassword": newPassword }
const url = globalUrl+'/api/v1/users/passwordchange'; const url = globalUrl + '/api/v1/users/passwordchange';
fetch(url, { fetch(url, {
mode: 'cors', mode: 'cors',
method: 'POST', method: 'POST',
@@ -127,13 +134,13 @@ const Admin = (props) => {
}), }),
) )
.catch(error => { .catch(error => {
alert.error("Err: "+error.toString()) alert.error("Err: " + error.toString())
}); });
} }
const deleteUser = (data) => { const deleteUser = (data) => {
// Just use this one? // Just use this one?
const url = globalUrl+'/api/v1/users/'+data.id const url = globalUrl + '/api/v1/users/' + data.id
fetch(url, { fetch(url, {
method: 'DELETE', method: 'DELETE',
credentials: "include", credentials: "include",
@@ -166,9 +173,9 @@ const Admin = (props) => {
console.log("INPUT: ", data) console.log("INPUT: ", data)
// Just use this one? // Just use this one?
var data = {"username": data.Username, "password": data.Password} var data = { "username": data.Username, "password": data.Password }
var baseurl = globalUrl var baseurl = globalUrl
const url = baseurl+'/api/v1/users/register'; const url = baseurl + '/api/v1/users/register';
fetch(url, { fetch(url, {
method: 'POST', method: 'POST',
credentials: "include", credentials: "include",
@@ -180,7 +187,7 @@ const Admin = (props) => {
.then(response => .then(response =>
response.json().then(responseJson => { response.json().then(responseJson => {
if (responseJson["success"] === false) { if (responseJson["success"] === false) {
setLoginInfo("Error in input: "+responseJson.reason) setLoginInfo("Error in input: " + responseJson.reason)
} else { } else {
setLoginInfo("") setLoginInfo("")
setModalOpen(false) setModalOpen(false)
@@ -195,7 +202,7 @@ const Admin = (props) => {
const deleteEnvironment = (name) => { const deleteEnvironment = (name) => {
// FIXME - add some check here ROFL // FIXME - add some check here ROFL
alert.info("Deleting environment "+name) alert.info("Deleting environment " + name)
var newEnv = [] var newEnv = []
for (var key in environments) { for (var key in environments) {
if (environments[key].Name == name) { if (environments[key].Name == name) {
@@ -206,7 +213,7 @@ const Admin = (props) => {
} }
// Just use this one? // Just use this one?
const url = globalUrl+'/api/v1/setenvironments'; const url = globalUrl + '/api/v1/setenvironments';
fetch(url, { fetch(url, {
method: 'PUT', method: 'PUT',
credentials: "include", credentials: "include",
@@ -233,11 +240,11 @@ const Admin = (props) => {
const submitEnvironment = (data) => { const submitEnvironment = (data) => {
// FIXME - add some check here ROFL // FIXME - add some check here ROFL
environments.push({"name": data.environment, "type": "onprem"}) environments.push({ "name": data.environment, "type": "onprem" })
// Just use this one? // Just use this one?
var baseurl = globalUrl var baseurl = globalUrl
const url = baseurl+'/api/v1/setenvironments'; const url = baseurl + '/api/v1/setenvironments';
fetch(url, { fetch(url, {
method: 'PUT', method: 'PUT',
credentials: "include", credentials: "include",
@@ -249,7 +256,7 @@ const Admin = (props) => {
.then(response => .then(response =>
response.json().then(responseJson => { response.json().then(responseJson => {
if (responseJson["success"] === false) { if (responseJson["success"] === false) {
setLoginInfo("Error in input: "+responseJson.reason) setLoginInfo("Error in input: " + responseJson.reason)
} else { } else {
setLoginInfo("") setLoginInfo("")
setModalOpen(false) setModalOpen(false)
@@ -263,7 +270,7 @@ const Admin = (props) => {
} }
const getSchedules = () => { const getSchedules = () => {
fetch(globalUrl+"/api/v1/workflows/schedules", { fetch(globalUrl + "/api/v1/workflows/schedules", {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -288,7 +295,7 @@ const Admin = (props) => {
} }
const getAppAuthentication = () => { const getAppAuthentication = () => {
fetch(globalUrl+"/api/v1/apps/authentication", { fetch(globalUrl + "/api/v1/apps/authentication", {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -318,7 +325,7 @@ const Admin = (props) => {
} }
const getEnvironments = () => { const getEnvironments = () => {
fetch(globalUrl+"/api/v1/getenvironments", { fetch(globalUrl + "/api/v1/getenvironments", {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -344,7 +351,7 @@ const Admin = (props) => {
} }
const getUsers = () => { const getUsers = () => {
fetch(globalUrl+"/api/v1/getusers", { fetch(globalUrl + "/api/v1/getusers", {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -378,7 +385,7 @@ const Admin = (props) => {
maxWidth: 1250, maxWidth: 1250,
margin: "auto", margin: "auto",
color: "white", color: "white",
backgroundColor: surfaceColor, backgroundColor: theme.palette.surfaceColor,
marginBottom: 10, marginBottom: 10,
padding: 20, padding: 20,
} }
@@ -388,11 +395,11 @@ const Admin = (props) => {
} }
const setUser = (userId, field, value) => { const setUser = (userId, field, value) => {
const data = {"user_id": userId} const data = { "user_id": userId }
data[field] = value data[field] = value
console.log("DATA: ", data) console.log("DATA: ", data)
fetch(globalUrl+"/api/v1/users/updateuser", { fetch(globalUrl + "/api/v1/users/updateuser", {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -412,9 +419,9 @@ const Admin = (props) => {
}) })
.then((responseJson) => { .then((responseJson) => {
if (!responseJson.success && responseJson.reason !== undefined) { if (!responseJson.success && responseJson.reason !== undefined) {
alert.error("Failed setting user: "+responseJson.reason) alert.error("Failed setting user: " + responseJson.reason)
} else { } else {
alert.success("Set the user field "+field+" to "+value) alert.success("Set the user field " + field + " to " + value)
} }
}) })
.catch(error => { .catch(error => {
@@ -425,9 +432,9 @@ const Admin = (props) => {
const generateApikey = (userId) => { const generateApikey = (userId) => {
const data = {"user_id": userId} const data = { "user_id": userId }
fetch(globalUrl+"/api/v1/generateapikey", { fetch(globalUrl + "/api/v1/generateapikey", {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -448,7 +455,7 @@ const Admin = (props) => {
.then((responseJson) => { .then((responseJson) => {
console.log("RESP: ", responseJson) console.log("RESP: ", responseJson)
if (!responseJson.success && responseJson.reason !== undefined) { if (!responseJson.success && responseJson.reason !== undefined) {
alert.error("Failed getting new: "+responseJson.reason) alert.error("Failed getting new: " + responseJson.reason)
} else { } else {
alert.success("Got new API key") alert.success("Got new API key")
} }
@@ -461,23 +468,23 @@ const Admin = (props) => {
const editAuthenticationModal = const editAuthenticationModal =
<Dialog modal <Dialog modal
open={selectedAuthenticationModalOpen} open={selectedAuthenticationModalOpen}
onClose={() => {setSelectedAuthenticationModalOpen(false)}} onClose={() => { setSelectedAuthenticationModalOpen(false) }}
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: surfaceColor, backgroundColor: theme.palette.surfaceColor,
color: "white", color: "white",
minWidth: "800px", minWidth: "800px",
minHeight: "320px", minHeight: "320px",
}, },
}} }}
> >
<DialogTitle><span style={{color: "white"}}>Edit authentication</span></DialogTitle> <DialogTitle><span style={{ color: "white" }}>Edit authentication</span></DialogTitle>
<DialogContent> <DialogContent>
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
<TextField <TextField
style={{backgroundColor: inputColor, flex: 3}} style={{ backgroundColor: theme.palette.inputColor, flex: 3 }}
InputProps={{ InputProps={{
style:{ style: {
height: 50, height: 50,
color: "white", color: "white",
}, },
@@ -494,7 +501,7 @@ const Admin = (props) => {
onChange={e => setNewPassword(e.target.value)} onChange={e => setNewPassword(e.target.value)}
/> />
<Button <Button
style={{maxHeight: 50, flex: 1}} style={{ maxHeight: 50, flex: 1 }}
variant="outlined" variant="outlined"
color="primary" color="primary"
onClick={() => onPasswordChange()} onClick={() => onPasswordChange()}
@@ -502,7 +509,7 @@ const Admin = (props) => {
Submit Submit
</Button> </Button>
</div> </div>
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: inputColor}}/> <Divider style={{ marginTop: 20, marginBottom: 20, backgroundColor: theme.palette.inputColor }} />
<Button <Button
style={{}} style={{}}
variant="outlined" variant="outlined"
@@ -525,23 +532,23 @@ const Admin = (props) => {
const editUserModal = const editUserModal =
<Dialog modal <Dialog modal
open={selectedUserModalOpen} open={selectedUserModalOpen}
onClose={() => {setSelectedUserModalOpen(false)}} onClose={() => { setSelectedUserModalOpen(false) }}
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: surfaceColor, backgroundColor: theme.palette.surfaceColor,
color: "white", color: "white",
minWidth: "800px", minWidth: "800px",
minHeight: "320px", minHeight: "320px",
}, },
}} }}
> >
<DialogTitle><span style={{color: "white"}}>Edit user</span></DialogTitle> <DialogTitle><span style={{ color: "white" }}>Edit user</span></DialogTitle>
<DialogContent> <DialogContent>
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
<TextField <TextField
style={{marginTop: 0, backgroundColor: inputColor, flex: 3}} style={{ marginTop: 0, backgroundColor: theme.palette.inputColor, flex: 3 }}
InputProps={{ InputProps={{
style:{ style: {
height: 50, height: 50,
color: "white", color: "white",
}, },
@@ -558,7 +565,7 @@ const Admin = (props) => {
onChange={e => setNewPassword(e.target.value)} onChange={e => setNewPassword(e.target.value)}
/> />
<Button <Button
style={{maxHeight: 50, flex: 1}} style={{ maxHeight: 50, flex: 1 }}
variant="outlined" variant="outlined"
color="primary" color="primary"
onClick={() => onPasswordChange()} onClick={() => onPasswordChange()}
@@ -566,7 +573,7 @@ const Admin = (props) => {
Submit Submit
</Button> </Button>
</div> </div>
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: inputColor}}/> <Divider style={{ marginTop: 20, marginBottom: 20, backgroundColor: theme.palette.inputColor }} />
<Button <Button
style={{}} style={{}}
variant="outlined" variant="outlined"
@@ -589,17 +596,17 @@ const Admin = (props) => {
const modalView = const modalView =
<Dialog modal <Dialog modal
open={modalOpen} open={modalOpen}
onClose={() => {setModalOpen(false)}} onClose={() => { setModalOpen(false) }}
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: surfaceColor, backgroundColor: theme.palette.surfaceColor,
color: "white", color: "white",
minWidth: "800px", minWidth: "800px",
minHeight: "320px", minHeight: "320px",
}, },
}} }}
> >
<DialogTitle><span style={{color: "white"}}> <DialogTitle><span style={{ color: "white" }}>
{curTab === 0 ? "Add user" : "Add environment"} {curTab === 0 ? "Add user" : "Add environment"}
</span></DialogTitle> </span></DialogTitle>
<DialogContent> <DialogContent>
@@ -608,10 +615,10 @@ const Admin = (props) => {
Username Username
<TextField <TextField
color="primary" color="primary"
style={{backgroundColor: inputColor}} style={{ backgroundColor: theme.palette.inputColor }}
autoFocus autoFocus
InputProps={{ InputProps={{
style:{ style: {
height: "50px", height: "50px",
color: "white", color: "white",
fontSize: "1em", fontSize: "1em",
@@ -629,9 +636,9 @@ const Admin = (props) => {
Password Password
<TextField <TextField
color="primary" color="primary"
style={{backgroundColor: inputColor}} style={{ backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
height: "50px", height: "50px",
color: "white", color: "white",
fontSize: "1em", fontSize: "1em",
@@ -653,10 +660,10 @@ const Admin = (props) => {
Environment Name Environment Name
<TextField <TextField
color="primary" color="primary"
style={{backgroundColor: inputColor}} style={{ backgroundColor: theme.palette.inputColor }}
autoFocus autoFocus
InputProps={{ InputProps={{
style:{ style: {
height: "50px", height: "50px",
color: "white", color: "white",
fontSize: "1em", fontSize: "1em",
@@ -671,14 +678,14 @@ const Admin = (props) => {
onChange={(event) => changeModalData("environment", event.target.value)} onChange={(event) => changeModalData("environment", event.target.value)}
/> />
</div> </div>
: null } : null}
{loginInfo} {loginInfo}
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button style={{borderRadius: "0px"}} onClick={() => setModalOpen(false)} color="primary"> <Button style={{ borderRadius: "0px" }} onClick={() => setModalOpen(false)} color="primary">
Cancel Cancel
</Button> </Button>
<Button variant="contained" style={{borderRadius: "0px"}} onClick={() => { <Button variant="contained" style={{ borderRadius: "0px" }} onClick={() => {
if (curTab === 0) { if (curTab === 0) {
submitUser(modalUser) submitUser(modalUser)
} else if (curTab === 2) { } else if (curTab === 2) {
@@ -692,11 +699,11 @@ const Admin = (props) => {
const usersView = curTab === 0 ? const usersView = curTab === 0 ?
<div> <div>
<div style={{marginTop: 20, marginBottom: 20,}}> <div style={{ marginTop: 20, marginBottom: 20, }}>
<h2 style={{display: "inline",}}>User management</h2> <h2 style={{ display: "inline", }}>User management</h2>
<span style={{marginLeft: 25}}>Add, edit, block or change passwords</span> <span style={{ marginLeft: 25 }}>Add, edit, block or change passwords</span>
</div> </div>
<div/> <div />
<Button <Button
style={{}} style={{}}
variant="contained" variant="contained"
@@ -705,28 +712,28 @@ const Admin = (props) => {
> >
Add user Add user
</Button> </Button>
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: inputColor}}/> <Divider style={{ marginTop: 20, marginBottom: 20, backgroundColor: theme.palette.inputColor }} />
<List> <List>
<ListItem> <ListItem>
<ListItemText <ListItemText
primary="Username" primary="Username"
style={{minWidth: 200, maxWidth: 200}} style={{ minWidth: 200, maxWidth: 200 }}
/> />
<ListItemText <ListItemText
primary="API key" primary="API key"
style={{minWidth: 350, maxWidth: 350, overflow: "hidden"}} style={{ minWidth: 350, maxWidth: 350, overflow: "hidden" }}
/> />
<ListItemText <ListItemText
primary="Role" primary="Role"
style={{minWidth: 150, maxWidth: 150}} style={{ minWidth: 150, maxWidth: 150 }}
/> />
<ListItemText <ListItemText
primary="Active" primary="Active"
style={{minWidth: 180, maxWidth: 180}} style={{ minWidth: 180, maxWidth: 180 }}
/> />
<ListItemText <ListItemText
primary="Actions" primary="Actions"
style={{minWidth: 180, maxWidth: 180}} style={{ minWidth: 180, maxWidth: 180 }}
/> />
</ListItem> </ListItem>
{users === undefined ? null : users.map(data => { {users === undefined ? null : users.map(data => {
@@ -734,15 +741,15 @@ const Admin = (props) => {
<ListItem> <ListItem>
<ListItemText <ListItemText
primary={data.username} primary={data.username}
style={{minWidth: 200, maxWidth: 200}} style={{ minWidth: 200, maxWidth: 200 }}
/> />
<ListItemText <ListItemText
primary={data.apikey === undefined || data.apikey.length === 0 ? "" : data.apikey} primary={data.apikey === undefined || data.apikey.length === 0 ? "" : data.apikey}
style={{maxWidth: 350, minWidth: 350,}} style={{ maxWidth: 350, minWidth: 350, }}
/> />
<ListItemText <ListItemText
primary= primary=
<Select {<Select
PaperProps={{ PaperProps={{
style: { style: {
} }
@@ -758,22 +765,22 @@ const Admin = (props) => {
console.log("VALUE: ", e.target.value) console.log("VALUE: ", e.target.value)
setUser(data.id, "role", e.target.value) setUser(data.id, "role", e.target.value)
}} }}
style={{backgroundColor: surfaceColor, color: "white", height: "50px"}} style={{ backgroundColor: theme.palette.surfaceColor, color: "white", height: "50px" }}
> >
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={"admin"}> <MenuItem style={{ backgroundColor: theme.palette.inputColor, color: "white" }} value={"admin"}>
Admin Admin
</MenuItem> </MenuItem>
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={"user"}> <MenuItem style={{ backgroundColor: theme.palette.inputColor, color: "white" }} value={"user"}>
User User
</MenuItem> </MenuItem>
</Select> </Select>}
style={{minWidth: 150, maxWidth: 150}} style = {{ minWidth: 150, maxWidth: 150}}
/> />
<ListItemText <ListItemText
primary={data.active ? "True" : "False"} primary={data.active ? "True" : "False"}
style={{minWidth: 180, maxWidth: 180}} style={{ minWidth: 180, maxWidth: 180 }}
/> />
<ListItemText style={{display: "flex"}}> <ListItemText style={{ display: "flex" }}>
<Button <Button
style={{}} style={{}}
variant="outlined" variant="outlined"
@@ -799,7 +806,7 @@ const Admin = (props) => {
<h2 style={{display: "inline",}}>Schedules</h2> <h2 style={{display: "inline",}}>Schedules</h2>
<span style={{marginLeft: 25}}>Schedules used in Workflows. Makes locating and control easier.</span> <span style={{marginLeft: 25}}>Schedules used in Workflows. Makes locating and control easier.</span>
</div> </div>
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: inputColor}}/> <Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: theme.palette.inputColor}}/>
<List> <List>
<ListItem> <ListItem>
<ListItemText <ListItemText
@@ -848,7 +855,7 @@ const Admin = (props) => {
<h2 style={{display: "inline",}}>App Authentication</h2> <h2 style={{display: "inline",}}>App Authentication</h2>
<span style={{marginLeft: 25}}>Control the authentication options for individual apps. <b>Actions can be destructive!</b></span> <span style={{marginLeft: 25}}>Control the authentication options for individual apps. <b>Actions can be destructive!</b></span>
</div> </div>
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: inputColor}}/> <Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: theme.palette.inputColor}}/>
<List> <List>
<ListItem> <ListItem>
<ListItemText <ListItemText
@@ -949,7 +956,7 @@ const Admin = (props) => {
> >
<CachedIcon /> <CachedIcon />
</Button> </Button>
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: inputColor}}/> <Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: theme.palette.inputColor}}/>
<List> <List>
<ListItem> <ListItem>
<ListItemText <ListItemText
@@ -977,7 +984,7 @@ const Admin = (props) => {
style={{minWidth: 200, maxWidth: 200, overflow: "hidden"}} style={{minWidth: 200, maxWidth: 200, overflow: "hidden"}}
/> />
<ListItemText> <ListItemText>
<Button type="outlined" style={{borderRadius: "0px"}} onClick={() => deleteEnvironment(environment.Name)} color="primary">Delete</Button> <Button variant="outlined" style={{borderRadius: "0px"}} onClick={() => deleteEnvironment(environment.Name)} color="primary">Delete</Button>
</ListItemText> </ListItemText>
</ListItem> </ListItem>
) )
@@ -986,6 +993,94 @@ const Admin = (props) => {
</div> </div>
: null : null
const organizationsTab = curTab === 5 ?
<div>
<div style={{marginTop: 20, marginBottom: 20,}}>
<h2 style={{display: "inline",}}>Organizations</h2>
<span style={{marginLeft: 25}}>Global admin: control organizations</span>
</div>
<Button
style={{}}
variant="contained"
color="primary"
onClick={() => setModalOpen(true)}
>
Add organization
</Button>
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: theme.palette.inputColor}}/>
<List>
<ListItem>
<ListItemText
primary="Name"
style={{minWidth: 150, maxWidth: 150}}
/>
<ListItemText
primary="Orborus running (TBD)"
style={{minWidth: 200, maxWidth: 200}}
/>
<ListItemText
primary="Actions"
style={{minWidth: 150, maxWidth: 150}}
/>
</ListItem>
<ListItem>
<ListItemText
primary="Enabled"
style={{minWidth: 150, maxWidth: 150}}
/>
<ListItemText
primary="false"
style={{minWidth: 200, maxWidth: 200}}
/>
<ListItemText
primary=<Switch checked={false} onChange={() => {console.log("INVERT")}} />
style={{minWidth: 150, maxWidth: 150}}
/>
</ListItem>
</List>
</div>
: null
const hybridTab = curTab === 4 ?
<div>
<div style={{marginTop: 20, marginBottom: 20,}}>
<h2 style={{display: "inline",}}>Hybrid</h2>
<span style={{marginLeft: 25}}></span>
</div>
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: theme.palette.inputColor}}/>
<List>
<ListItem>
<ListItemText
primary="Name"
style={{minWidth: 150, maxWidth: 150}}
/>
<ListItemText
primary="Orborus running (TBD)"
style={{minWidth: 200, maxWidth: 200}}
/>
<ListItemText
primary="Actions"
style={{minWidth: 150, maxWidth: 150}}
/>
</ListItem>
<ListItem>
<ListItemText
primary="Enabled"
style={{minWidth: 150, maxWidth: 150}}
/>
<ListItemText
primary="false"
style={{minWidth: 200, maxWidth: 200}}
/>
<ListItemText
primary=<Switch checked={false} onChange={() => {console.log("INVERT")}} />
style={{minWidth: 150, maxWidth: 150}}
/>
</ListItem>
</List>
</div>
: null
// primary={environment.Registered ? "true" : "false"} // primary={environment.Registered ? "true" : "false"}
const setConfig = (event, newValue) => { const setConfig = (event, newValue) => {
@@ -1001,20 +1096,22 @@ const Admin = (props) => {
setCurTab(newValue) setCurTab(newValue)
} }
const iconStyle = {marginRight: 10}
const data = const data =
<div style={{minWidth: 1366, margin: "auto"}}> <div style={{minWidth: 1366, margin: "auto"}}>
<Paper style={paperStyle}> <Paper style={paperStyle}>
<Tabs <Tabs
value={curTab} value={curTab}
indicatorColor="primary" indicatorColor="primary"
textColor="white"
onChange={setConfig} onChange={setConfig}
aria-label="disabled tabs example" aria-label="disabled tabs example"
> >
<Tab label="Users" /> <Tab label=<span><AccessibilityNewIcon style={iconStyle} />Users</span> />
<Tab label="App Authentication"/> <Tab label=<span><LockIcon style={iconStyle} />App Authentication</span>/>
<Tab label="Environments"/> <Tab label=<span><EcoIcon style={iconStyle} />Environments</span>/>
<Tab label="Schedules"/> <Tab label=<span><ScheduleIcon style={iconStyle} />Schedules</span> />
{window.location.protocol == "http:" && window.location.port === "3000" ? <Tab label=<span><CloudIcon style={iconStyle} /> Hybrid</span>/> : null}
{window.location.protocol == "http:" && window.location.port === "3000" ? <Tab label=<span><BusinessIcon style={iconStyle} /> Organizations</span>/> : null}
</Tabs> </Tabs>
<Divider style={{marginTop: 0, marginBottom: 10, backgroundColor: "rgb(91, 96, 100)"}} /> <Divider style={{marginTop: 0, marginBottom: 10, backgroundColor: "rgb(91, 96, 100)"}} />
<div style={{padding: 15}}> <div style={{padding: 15}}>
@@ -1022,6 +1119,8 @@ const Admin = (props) => {
{usersView} {usersView}
{environmentView} {environmentView}
{schedulesView} {schedulesView}
{hybridTab}
{organizationsTab}
</div> </div>
</Paper> </Paper>
</div> </div>
@@ -68,8 +68,7 @@ import CytoscapeComponent from 'react-cytoscapejs';
import undoRedo from 'cytoscape-undo-redo'; import undoRedo from 'cytoscape-undo-redo';
import Draggable from 'react-draggable'; import Draggable from 'react-draggable';
import environmentdata from './environmentdata'; import cytoscapestyle from '../defaultCytoscapeStyle';
import cytoscapestyle from './defaultCytoscapeStyle';
import cxtmenu from 'cytoscape-cxtmenu'; import cxtmenu from 'cytoscape-cxtmenu';
import { w3cwebsocket as W3CWebSocket } from "websocket"; import { w3cwebsocket as W3CWebSocket } from "websocket";
@@ -950,6 +949,10 @@ const AngularWorkflow = (props) => {
if (curaction.selectedAuthentication === null || curaction.selectedAuthentication === undefined || curaction.selectedAuthentication.length === "") { if (curaction.selectedAuthentication === null || curaction.selectedAuthentication === undefined || curaction.selectedAuthentication.length === "") {
curaction.selectedAuthentication = {} curaction.selectedAuthentication = {}
} }
} else {
curaction.authentication = []
curaction.authentication_id = ""
curaction.selectedAuthentication = {}
} }
setSelectedApp(curapp) setSelectedApp(curapp)
@@ -2998,7 +3001,7 @@ const AngularWorkflow = (props) => {
paddingLeft: 10, paddingLeft: 10,
minHeight: "100%", minHeight: "100%",
zIndex: 1000, zIndex: 1000,
resize: "horizontal", resize: "vertical",
overflow: "auto", overflow: "auto",
} }
@@ -3513,14 +3516,6 @@ const AngularWorkflow = (props) => {
<div style={{flex: "10"}}> <div style={{flex: "10"}}>
<b>{data.name} </b> <b>{data.name} </b>
</div> </div>
<Tooltip color="primary" title="Static data" placement="top">
<div style={{cursor: "pointer", color: staticcolor}} onClick={(e) => {
e.preventDefault()
changeActionParameterVariant("STATIC_VALUE")
}}>
<CreateIcon />
</div>
</Tooltip>
</div> </div>
{datafield} {datafield}
</div> </div>
@@ -3553,10 +3548,20 @@ const AngularWorkflow = (props) => {
<FormControl> <FormControl>
<DialogTitle><div style={{color:"white"}}>Condition</div></DialogTitle> <DialogTitle><div style={{color:"white"}}>Condition</div></DialogTitle>
<DialogContent style={{display: "flex"}}> <DialogContent style={{display: "flex"}}>
<Tooltip color="primary" title={conditionValue.configuration ? "Negated" : "Default"} placement="top">
<Button color="primary" variant={conditionValue.configuration ? "contained" : "outlined"} style={{margin: "auto", height: 50, marginBottom: 0, marginRight: 5}} onClick={(e) => {
console.log("VALUE: ", conditionValue.configuration)
conditionValue.configuration = !conditionValue.configuration
setConditionValue(conditionValue)
setUpdate("condition "+conditionValue.configuration)
}}>
{conditionValue.configuration ? "!" : "="}
</Button>
</Tooltip>
<div style={{flex: "2"}}> <div style={{flex: "2"}}>
<AppConditionHandler tmpdata={sourceValue} setData={setSourceValue} type={"source"} /> <AppConditionHandler tmpdata={sourceValue} setData={setSourceValue} type={"source"} />
</div> </div>
<div style={{flex: "1", margin: "auto", marginBottom: "0px"}}> <div style={{flex: "1", margin: "auto", marginBottom: 0, marginLeft: 5, marginRight: 5,}}>
<Button color="primary" variant="outlined" style={{height: "50px",}} fullWidth aria-haspopup="true" onClick={(e) => {setVariableAnchorEl(e.currentTarget)}}> <Button color="primary" variant="outlined" style={{height: "50px",}} fullWidth aria-haspopup="true" onClick={(e) => {setVariableAnchorEl(e.currentTarget)}}>
{conditionValue.value} {conditionValue.value}
</Button> </Button>
@@ -3621,7 +3626,6 @@ const AngularWorkflow = (props) => {
setVariableAnchorEl(null) setVariableAnchorEl(null)
}} key={"less than"}>less than</MenuItem> }} key={"less than"}>less than</MenuItem>
</Menu> </Menu>
</div> </div>
<div style={{flex: "2"}}> <div style={{flex: "2"}}>
<AppConditionHandler tmpdata={destinationValue} setData={setDestinationValue} type={"destination"} /> <AppConditionHandler tmpdata={destinationValue} setData={setDestinationValue} type={"destination"} />
@@ -4774,7 +4778,7 @@ const AngularWorkflow = (props) => {
<Divider style={{backgroundColor: "white", marginTop: 10, marginBottom: 10,}}/> <Divider style={{backgroundColor: "white", marginTop: 10, marginBottom: 10,}}/>
<FormControlLabel <FormControlLabel
style={{marginBottom: 15, color: "white",}} style={{marginBottom: 15, color: "white",}}
label=<div style={{color: "white"}}>Exit on Error</div> label={<div style={{color: "white"}}>Exit on Error</div>}
control={ control={
<Switch checked={workflow.configuration.exit_on_error} onChange={() => { <Switch checked={workflow.configuration.exit_on_error} onChange={() => {
workflow.configuration.exit_on_error = !workflow.configuration.exit_on_error workflow.configuration.exit_on_error = !workflow.configuration.exit_on_error
@@ -4786,7 +4790,7 @@ const AngularWorkflow = (props) => {
/> />
<FormControlLabel <FormControlLabel
style={{marginBottom: 15, color: "white",}} style={{marginBottom: 15, color: "white",}}
label=<div style={{color: "white"}}>Start from top</div> label={<div style={{color: "white"}}>Start from top</div>}
control={ control={
<Switch checked={workflow.configuration.start_from_top} onChange={() => { <Switch checked={workflow.configuration.start_from_top} onChange={() => {
workflow.configuration.start_from_top = !workflow.configuration.start_from_top workflow.configuration.start_from_top = !workflow.configuration.start_from_top
@@ -5114,7 +5118,7 @@ const AngularWorkflow = (props) => {
<h2>Executing Workflow</h2> <h2>Executing Workflow</h2>
<FormControlLabel <FormControlLabel
style={{color: "white", marginBottom: "0px", marginTop: "10px"}} style={{color: "white", marginBottom: "0px", marginTop: "10px"}}
label=<div style={{color: "white"}}>Show failed / skipped actions</div> label={<div style={{color: "white"}}>Show failed / skipped actions</div>}
control={ control={
<Switch checked={showSkippedActions} onChange={() => {setShowSkippedActions(!showSkippedActions)}} /> <Switch checked={showSkippedActions} onChange={() => {setShowSkippedActions(!showSkippedActions)}} />
} }
@@ -286,7 +286,7 @@ const Apps = (props) => {
} }
return ( return (
<Paper square style={paperAppStyle} onClick={() => { <Paper square key={data.id} style={paperAppStyle} onClick={() => {
if (selectedApp.id !== data.id) { if (selectedApp.id !== data.id) {
setSelectedApp(data) setSelectedApp(data)
console.log(data) console.log(data)
@@ -515,7 +515,7 @@ const Apps = (props) => {
newActionname = newActionname.replace("_", " ") newActionname = newActionname.replace("_", " ")
newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1) newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1)
return ( return (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}> <MenuItem key={data.name} style={{backgroundColor: inputColor, color: "white"}} value={data}>
{newActionname} {newActionname}
</MenuItem> </MenuItem>
@@ -540,7 +540,7 @@ const Apps = (props) => {
const circleSize = 10 const circleSize = 10
return ( return (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}> <MenuItem key={data.name} style={{backgroundColor: inputColor, color: "white"}} value={data}>
<div style={{width: circleSize, height: circleSize, borderRadius: circleSize / 2, backgroundColor: itemColor, marginRight: "10px"}}/> <div style={{width: circleSize, height: circleSize, borderRadius: circleSize / 2, backgroundColor: itemColor, marginRight: "10px"}}/>
{data.name} {data.name}
@@ -654,7 +654,7 @@ const Apps = (props) => {
{isLoading ? <CircularProgress style={{marginTop: 13, marginRight: 15}} /> : null} {isLoading ? <CircularProgress style={{marginTop: 13, marginRight: 15}} /> : null}
<FormControlLabel <FormControlLabel
style={{color: "white", marginBottom: "0px", marginTop: "10px"}} style={{color: "white", marginBottom: "0px", marginTop: "10px"}}
label=<div style={{color: "white"}}>Search OpenAPI</div> label={<div style={{color: "white"}}>Search OpenAPI</div>}
control={<Switch checked={searchBackend} onChange={() => { control={<Switch checked={searchBackend} onChange={() => {
handleSearchChange("") handleSearchChange("")
setSearchBackend(!searchBackend)} setSearchBackend(!searchBackend)}
@@ -743,7 +743,7 @@ const Apps = (props) => {
null null
// Load data e.g. from github // Load data e.g. from github
const getSpecificApps = (url) => { const getSpecificApps = (url, forceUpdate) => {
setValidation(true) setValidation(true)
setIsLoading(true) setIsLoading(true)
@@ -761,6 +761,8 @@ const Apps = (props) => {
parsedData["field_2"] = field2 parsedData["field_2"] = field2
} }
parsedData["force_update"] = forceUpdate
alert.success("Getting specific apps from your URL.") alert.success("Getting specific apps from your URL.")
var cors = "cors" var cors = "cors"
fetch(globalUrl+"/api/v1/apps/get_existing", { fetch(globalUrl+"/api/v1/apps/get_existing", {
@@ -977,8 +979,8 @@ const Apps = (props) => {
window.location.href = "/apps/new?id="+appValidation window.location.href = "/apps/new?id="+appValidation
} }
const handleGithubValidation = () => { const handleGithubValidation = (forceUpdate) => {
getSpecificApps(openApi) getSpecificApps(openApi, forceUpdate)
setLoadAppsModalOpen(false) setLoadAppsModalOpen(false)
} }
@@ -1098,7 +1100,12 @@ const Apps = (props) => {
Cancel Cancel
</Button> </Button>
<Button style={{borderRadius: "0px"}} disabled={openApi.length === 0 || !openApi.includes("http")} onClick={() => { <Button style={{borderRadius: "0px"}} disabled={openApi.length === 0 || !openApi.includes("http")} onClick={() => {
handleGithubValidation() handleGithubValidation(true)
}} color="primary">
Force update
</Button>
<Button variant="outlined" style={{float: "left", borderRadius: "0px"}} disabled={openApi.length === 0 || !openApi.includes("http")} onClick={() => {
handleGithubValidation(false)
}} color="primary"> }} color="primary">
Submit Submit
</Button> </Button>
@@ -1,11 +1,13 @@
import React, {useState} from 'react'; import React, { useState } from 'react';
import {BrowserView, MobileView} from "react-device-detect"; import { BrowserView, MobileView } from "react-device-detect";
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
import Button from '@material-ui/core/Button'; 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';
const bodyDivStyle = { const bodyDivStyle = {
margin: "auto", margin: "auto",
textAlign: "center", textAlign: "center",
@@ -13,11 +15,11 @@ const bodyDivStyle = {
} }
// Should be different if logged in :| // Should be different if logged in :|
const Contact = (props) => { const Contact = (props) => {
const { globalUrl, isLoaded, surfaceColor, inputColor } = props; const { globalUrl, isLoaded } = props;
const theme = useTheme();
const boxStyle = { const boxStyle = {
flex: "1", flex: "1",
@@ -27,7 +29,7 @@ const Contact = (props) => {
paddingRight: "30px", paddingRight: "30px",
paddingBottom: "30px", paddingBottom: "30px",
paddingTop: "30px", paddingTop: "30px",
backgroundColor: surfaceColor, backgroundColor: theme.palette.surfaceColor,
display: "flex", display: "flex",
flexDirection: "column" flexDirection: "column"
} }
@@ -58,7 +60,7 @@ const Contact = (props) => {
} }
console.log(data) console.log(data)
fetch(globalUrl+"/api/v1/contact", { fetch(globalUrl + "/api/v1/contact", {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -83,18 +85,18 @@ const Contact = (props) => {
const landingpageDataBrowser = const landingpageDataBrowser =
<div> <div>
<div style={bodyTextStyle}> <div style={bodyTextStyle}>
<h3 style={{color: "#f85a3e"}}>Contact us</h3> <h3 style={{ color: "#f85a3e" }}>Contact us</h3>
<h2>Lets talk!</h2> <h2>Lets talk!</h2>
</div> </div>
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
<Paper style={boxStyle}> <Paper style={boxStyle}>
<h2>Contact Details</h2> <h2>Contact Details</h2>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField <TextField
required required
style={{flex: "1", marginRight: "15px", backgroundColor: inputColor}} style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
@@ -109,9 +111,9 @@ const Contact = (props) => {
onChange={e => setFirstname(e.target.value)} onChange={e => setFirstname(e.target.value)}
/> />
<TextField <TextField
style={{flex: "1", marginLeft: "15px", backgroundColor: inputColor}} style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
@@ -126,11 +128,11 @@ const Contact = (props) => {
onChange={e => setLastname(e.target.value)} onChange={e => setLastname(e.target.value)}
/> />
</div> </div>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField <TextField
style={{flex: "1", marginRight: "15px", backgroundColor: inputColor}} style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
@@ -145,9 +147,9 @@ const Contact = (props) => {
onChange={e => setTitle(e.target.value)} onChange={e => setTitle(e.target.value)}
/> />
<TextField <TextField
style={{flex: "1", marginLeft: "15px", backgroundColor: inputColor}} style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
@@ -162,12 +164,12 @@ const Contact = (props) => {
onChange={e => setCompanyname(e.target.value)} onChange={e => setCompanyname(e.target.value)}
/> />
</div> </div>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField <TextField
required required
style={{flex: "1", marginRight: "15px", backgroundColor: inputColor}} style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
@@ -182,9 +184,9 @@ const Contact = (props) => {
onChange={e => setEmail(e.target.value)} onChange={e => setEmail(e.target.value)}
/> />
<TextField <TextField
style={{flex: "1", marginLeft: "15px", backgroundColor: inputColor}} style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
@@ -199,19 +201,19 @@ const Contact = (props) => {
onChange={e => setPhone(e.target.value)} onChange={e => setPhone(e.target.value)}
/> />
</div> </div>
<div style={{flex: 1}}> <div style={{ flex: 1 }}>
<h2>Message</h2> <h2>Message</h2>
</div> </div>
<div style={{flex: 4}}> <div style={{ flex: 4 }}>
<TextField <TextField
multiline multiline
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
color="primary" color="primary"
style={{flex: "1", backgroundColor: inputColor}} style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
rows="6" rows="6"
fullWidth={true} fullWidth={true}
placeholder="What can we help you with?" placeholder="What can we help you with?"
@@ -223,7 +225,7 @@ const Contact = (props) => {
</div> </div>
<Button <Button
disabled={email.length <= 0 || message.length <= 0} disabled={email.length <= 0 || message.length <= 0}
style={{width: "100%", height: "60px", marginTop: "10px"}} style={{ width: "100%", height: "60px", marginTop: "10px" }}
variant="contained" variant="contained"
color="primary" color="primary"
onClick={submitContact} onClick={submitContact}
@@ -236,20 +238,20 @@ const Contact = (props) => {
</div> </div>
const landingpageDataMobile = const landingpageDataMobile =
<div style={{paddingBottom: "50px"}}> <div style={{ paddingBottom: "50px" }}>
<div style={{color: "white", textAlign: "center"}}> <div style={{ color: "white", textAlign: "center" }}>
<h3 style={{color: "#f85a3e"}}>Contact us</h3> <h3 style={{ color: "#f85a3e" }}>Contact us</h3>
<h2>Lets talk!</h2> <h2>Lets talk!</h2>
</div> </div>
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
<Paper style={boxStyle}> <Paper style={boxStyle}>
<h2>Contact Details</h2> <h2>Contact Details</h2>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField <TextField
required required
style={{flex: "1", backgroundColor: inputColor}} style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
@@ -264,12 +266,12 @@ const Contact = (props) => {
onChange={e => setFirstname(e.target.value)} onChange={e => setFirstname(e.target.value)}
/> />
</div> </div>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField <TextField
required required
style={{flex: "1", backgroundColor: inputColor}} style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
@@ -284,15 +286,15 @@ const Contact = (props) => {
onChange={e => setEmail(e.target.value)} onChange={e => setEmail(e.target.value)}
/> />
</div> </div>
<div style={{flex: 1}}> <div style={{ flex: 1 }}>
<h2>Message</h2> <h2>Message</h2>
</div> </div>
<div style={{flex: 4}}> <div style={{ flex: 4 }}>
<TextField <TextField
multiline multiline
style={{flex: "1", backgroundColor: inputColor}} style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
style:{ style: {
color: "white", color: "white",
}, },
}} }}
@@ -308,7 +310,7 @@ const Contact = (props) => {
</div> </div>
<Button <Button
disabled={email.length <= 0 || message.length <= 0} disabled={email.length <= 0 || message.length <= 0}
style={{width: "100%", height: "60px", marginTop: "10px"}} style={{ width: "100%", height: "60px", marginTop: "10px" }}
variant="contained" variant="contained"
color="primary" color="primary"
onClick={submitContact} onClick={submitContact}
@@ -334,7 +336,7 @@ const Contact = (props) => {
<div> <div>
</div> </div>
return( return (
<div> <div>
{loadedCheck} {loadedCheck}
</div> </div>
@@ -35,7 +35,7 @@ import {
chartExample2, chartExample2,
chartExample3, chartExample3,
chartExample4 chartExample4
} from "./charts.js"; } from "../charts.js";
// This is the start of a dashboard that can be used. // This is the start of a dashboard that can be used.
// What data do we fill in here? Idk // What data do we fill in here? Idk
@@ -34,9 +34,6 @@ import DeleteIcon from '@material-ui/icons/Delete';
import Downshift from 'downshift'; import Downshift from 'downshift';
import deburr from 'lodash/deburr'; import deburr from 'lodash/deburr';
//import appdata from './appdata';
const EditSchedule = (props) => { const EditSchedule = (props) => {
const { globalUrl } = props; const { globalUrl } = props;
@@ -6,8 +6,8 @@ import Divider from '@material-ui/core/Divider';
import Select from '@material-ui/core/Select'; import Select from '@material-ui/core/Select';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import WebhookImage from './assets/img/webhook.png'; import WebhookImage from '../assets/img/webhook.png';
import KafkaImage from './assets/img/kafka.png'; import KafkaImage from '../assets/img/kafka.png';
import EditWorkflow from "./EditWorkflow"; import EditWorkflow from "./EditWorkflow";
@@ -1,10 +1,12 @@
/* eslint-disable react/no-multi-comp */ /* eslint-disable react/no-multi-comp */
import React, {useState} from 'react'; import React, { useState } from 'react';
import { makeStyles } from '@material-ui/styles'; import { makeStyles } from '@material-ui/styles';
import TextField from '@material-ui/core/TextField'; import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
import { useTheme } from '@material-ui/core/styles';
const hrefStyle = { const hrefStyle = {
color: "white", color: "white",
@@ -17,16 +19,6 @@ const bodyDivStyle = {
width: "500px", width: "500px",
} }
const surfaceColor = "#27292D"
const inputColor = "#383B40"
const boxStyle = {
paddingLeft: "30px",
paddingRight: "30px",
paddingBottom: "30px",
paddingTop: "30px",
backgroundColor: surfaceColor,
}
const useStyles = makeStyles({ const useStyles = makeStyles({
notchedOutline: { notchedOutline: {
@@ -35,6 +27,8 @@ const useStyles = makeStyles({
}); });
const LoginDialog = props => { const LoginDialog = props => {
const theme = useTheme();
const { globalUrl, isLoaded, isLoggedIn, setIsLoggedIn, setCookie, register } = props; const { globalUrl, isLoaded, isLoggedIn, setIsLoggedIn, setCookie, register } = props;
const [username, setUsername] = useState(""); const [username, setUsername] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
@@ -56,7 +50,7 @@ const LoginDialog = props => {
const checkAdmin = () => { const checkAdmin = () => {
const url = globalUrl+'/api/v1/checkusers'; const url = globalUrl + '/api/v1/checkusers';
fetch(url, { fetch(url, {
method: 'GET', method: 'GET',
headers: { headers: {
@@ -89,10 +83,10 @@ const LoginDialog = props => {
// FIXME - add some check here ROFL // FIXME - add some check here ROFL
// Just use this one? // Just use this one?
var data = {"username": username, "password": password} var data = { "username": username, "password": password }
var baseurl = globalUrl var baseurl = globalUrl
if (register) { if (register) {
var url = baseurl+'/api/v1/users/login'; var url = baseurl + '/api/v1/users/login';
fetch(url, { fetch(url, {
mode: 'cors', mode: 'cors',
method: 'POST', method: 'POST',
@@ -111,7 +105,7 @@ const LoginDialog = props => {
} else { } else {
setLoginInfo("Successful login, rerouting") setLoginInfo("Successful login, rerouting")
for (var key in responseJson["cookies"]) { 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)
@@ -123,7 +117,7 @@ const LoginDialog = props => {
setLoginInfo("Error in userdata: " + error) setLoginInfo("Error in userdata: " + error)
}); });
} else { } else {
url = baseurl+'/api/v1/users/register'; url = baseurl + '/api/v1/users/register';
fetch(url, { fetch(url, {
method: 'POST', method: 'POST',
body: JSON.stringify(data), body: JSON.stringify(data),
@@ -169,22 +163,29 @@ const LoginDialog = props => {
// <DialogTitle>{formtitle}</DialogTitle> // <DialogTitle>{formtitle}</DialogTitle>
console.log("THEME: ", theme.palette.surfaceColor)
const basedata = const basedata =
<div style={bodyDivStyle}> <div style={bodyDivStyle}>
<Paper style={boxStyle}> <Paper style={{
<form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px", color: "white",}}> paddingLeft: "30px",
paddingRight: "30px",
paddingBottom: "30px",
paddingTop: "30px",
backgroundColor: theme.palette.surfaceColor,
}}>
<form onSubmit={onSubmit} style={{ margin: "15px 15px 15px 15px", color: "white", }}>
<h2>{formtitle}</h2> <h2>{formtitle}</h2>
Username Username
<div> <div>
<TextField <TextField
color="primary" color="primary"
style={{backgroundColor: inputColor}} style={{ backgroundColor: theme.palette.inputColor }}
autoFocus autoFocus
InputProps={{ InputProps={{
classes: { classes: {
notchedOutline: classes.notchedOutline, notchedOutline: classes.notchedOutline,
}, },
style:{ style: {
height: "50px", height: "50px",
color: "white", color: "white",
fontSize: "1em", fontSize: "1em",
@@ -204,12 +205,12 @@ const LoginDialog = props => {
<div> <div>
<TextField <TextField
color="primary" color="primary"
style={{backgroundColor: inputColor,}} style={{ backgroundColor: theme.palette.inputColor }}
InputProps={{ InputProps={{
classes: { classes: {
notchedOutline: classes.notchedOutline, notchedOutline: classes.notchedOutline,
}, },
style:{ style: {
height: "50px", height: "50px",
color: "white", color: "white",
fontSize: "1em", fontSize: "1em",
@@ -226,11 +227,11 @@ const LoginDialog = props => {
onChange={onChangePass} onChange={onChangePass}
/> />
</div> </div>
<div style={{display: "flex", marginTop: "15px"}}> <div style={{ display: "flex", marginTop: "15px" }}>
<Button color="primary" variant="contained" type="submit" style={{flex: "1", marginRight: "5px"}} disabled={!handleValidateForm()}>SUBMIT</Button> <Button color="primary" variant="contained" type="submit" style={{ flex: "1", marginRight: "5px" }} disabled={!handleValidateForm()}>SUBMIT</Button>
</div> </div>
<div style={{marginTop: "10px"}}> <div style={{ marginTop: "10px" }}>
{loginInfo} {loginInfo}
</div> </div>
</form> </form>
@@ -7,23 +7,11 @@ import {Link} from 'react-router-dom';
import TextField from '@material-ui/core/TextField'; import TextField from '@material-ui/core/TextField';
import { useAlert } from "react-alert"; import { useAlert } from "react-alert";
import { useTheme } from '@material-ui/core/styles';
//const tmpdata = {
// "username": "frikky",
// "firstname": "fred",
// "lastname": "ode",
// "title": "topkek",
// "companyname": "company here",
// "email": "your email pls",
// "phone": "PHONE!!",
//}
// FIXME - add fetch for data fields
// FIXME - remove tmpdata
// FIXME: Use isLoggedIn :)
const Settings = (props) => { const Settings = (props) => {
const { globalUrl, isLoaded, userdata, surfaceColor, inputColor } = props; const { globalUrl, isLoaded, userdata, } = props;
const theme = useTheme();
const alert = useAlert() const alert = useAlert()
const [username, setUsername] = useState(""); const [username, setUsername] = useState("");
@@ -61,7 +49,7 @@ const Settings = (props) => {
paddingRight: "30px", paddingRight: "30px",
paddingBottom: "30px", paddingBottom: "30px",
paddingTop: "30px", paddingTop: "30px",
backgroundColor: surfaceColor, backgroundColor: theme.palette.surfaceColor,
display: "flex", display: "flex",
flexDirection: "column" flexDirection: "column"
} }
@@ -190,7 +178,7 @@ const Settings = (props) => {
<h2>APIKEY</h2> <h2>APIKEY</h2>
<Link to="/docs/API#authentication" style={{textDecoration: "none", color: "#f85a3e"}}>What is the API key used for?</Link> <Link to="/docs/API#authentication" style={{textDecoration: "none", color: "#f85a3e"}}>What is the API key used for?</Link>
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1"}} style={{backgroundColor: theme.palette.inputColor, flex: "1"}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -218,7 +206,7 @@ const Settings = (props) => {
<h2>Settings</h2> <h2>Settings</h2>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{flex: "1", display: "flex", flexDirection: "row"}}>
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1"}} style={{backgroundColor: theme.palette.inputColor, flex: "1"}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -240,7 +228,7 @@ const Settings = (props) => {
</div> </div>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{flex: "1", display: "flex", flexDirection: "row"}}>
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1", marginRight: "15px"}} style={{backgroundColor: theme.palette.inputColor, flex: "1", marginRight: "15px"}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -260,7 +248,7 @@ const Settings = (props) => {
onChange={e => setFirstname(e.target.value)} onChange={e => setFirstname(e.target.value)}
/> />
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1", marginLeft: "15px"}} style={{backgroundColor: theme.palette.inputColor, flex: "1", marginLeft: "15px"}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -282,7 +270,7 @@ const Settings = (props) => {
</div> </div>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{flex: "1", display: "flex", flexDirection: "row"}}>
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1", marginRight: "15px",}} style={{backgroundColor: theme.palette.inputColor, flex: "1", marginRight: "15px",}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -302,7 +290,7 @@ const Settings = (props) => {
onChange={e => setTitle(e.target.value)} onChange={e => setTitle(e.target.value)}
/> />
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1", marginLeft: "15px"}} style={{backgroundColor: theme.palette.inputColor, flex: "1", marginLeft: "15px"}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -324,7 +312,7 @@ const Settings = (props) => {
</div> </div>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{flex: "1", display: "flex", flexDirection: "row"}}>
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1", marginRight: "15px",}} style={{backgroundColor: theme.palette.inputColor, flex: "1", marginRight: "15px",}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -344,7 +332,7 @@ const Settings = (props) => {
onChange={e => setEmail(e.target.value)} onChange={e => setEmail(e.target.value)}
/> />
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1", marginLeft: "15px",}} style={{backgroundColor: theme.palette.inputColor, flex: "1", marginLeft: "15px",}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -379,7 +367,7 @@ const Settings = (props) => {
<h2>Password</h2> <h2>Password</h2>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{flex: "1", display: "flex", flexDirection: "row"}}>
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1"}} style={{backgroundColor: theme.palette.inputColor, flex: "1"}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -400,7 +388,7 @@ const Settings = (props) => {
</div> </div>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{flex: "1", display: "flex", flexDirection: "row"}}>
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1", marginRight: "15px",}} style={{backgroundColor: theme.palette.inputColor, flex: "1", marginRight: "15px",}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -419,7 +407,7 @@ const Settings = (props) => {
onChange={e => setNewPassword(e.target.value)} onChange={e => setNewPassword(e.target.value)}
/> />
<TextField <TextField
style={{backgroundColor: inputColor, flex: "1", marginLeft: "15px",}} style={{backgroundColor: theme.palette.inputColor, flex: "1", marginLeft: "15px",}}
InputProps={{ InputProps={{
style:{ style:{
height: "50px", height: "50px",
@@ -15,8 +15,8 @@ import DialogTitle from '@material-ui/core/DialogTitle';
import DialogActions from '@material-ui/core/DialogActions'; import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent'; import DialogContent from '@material-ui/core/DialogContent';
import WebhookImage from './assets/img/webhook.png'; import WebhookImage from '../assets/img/webhook.png';
import KafkaImage from './assets/img/kafka.png'; import KafkaImage from '../assets/img/kafka.png';
const Webhooks = (props) => { const Webhooks = (props) => {
const { globalUrl, isLoaded } = props; const { globalUrl, isLoaded } = props;
@@ -563,7 +563,7 @@ const Workflows = (props) => {
} }
return ( return (
<Paper square style={resultPaperAppStyle} onClick={() => {}}> <Paper key={data.id} square style={resultPaperAppStyle} onClick={() => {}}>
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", marginRight: "5px", width: boxWidth, backgroundColor: boxColor}}> <div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", marginRight: "5px", width: boxWidth, backgroundColor: boxColor}}>
</div> </div>
<Grid container style={{margin: "10px 10px 10px 10px", flex: "1"}}> <Grid container style={{margin: "10px 10px 10px 10px", flex: "1"}}>
@@ -988,7 +988,7 @@ const Workflows = (props) => {
<div style={{flex: "1"}}> <div style={{flex: "1"}}>
<FormControlLabel <FormControlLabel
style={{color: "white", marginBottom: "0px", marginTop: "10px"}} style={{color: "white", marginBottom: "0px", marginTop: "10px"}}
label=<div style={{color: "white"}}>Collapse results</div> label={<div style={{color: "white"}}>Collapse results</div>}
control={<Switch checked={collapseJson} onChange={() => {setCollapseJson(!collapseJson)}} />} control={<Switch checked={collapseJson} onChange={() => {setCollapseJson(!collapseJson)}} />}
/> />
</div> </div>
+15 -13
View File
@@ -78,10 +78,11 @@ func init() {
// Skip random containers. Only handle things related to Shuffle. // Skip random containers. Only handle things related to Shuffle.
for _, container := range containers { for _, container := range containers {
found := false found := false
//log.Printf("Running? %#v", container)
if container.State != "running" { // Bad states - it might just be created sometimes, leading to now netowkr
continue //if container.State == "restarting" || container.State == "paused" || container.State == "exited" || container.State == "dead" {
} // continue
//}
for _, name := range container.Names { for _, name := range container.Names {
if !strings.Contains(strings.ToLower(name), containerIdentifier) { if !strings.Contains(strings.ToLower(name), containerIdentifier) {
@@ -120,17 +121,10 @@ func deployWorker(image string, identifier string, env []string) {
}, },
} }
// ROFL: https://docker-py.readthedocs.io/en/1.4.0/volumes/
config := &container.Config{
Image: image,
Env: env,
}
// Look for Shuffle network and set it // Look for Shuffle network and set it
// FIXME: Move this out of here and have it be a global setting. During init?
networkConfig := &network.NetworkingConfig{} networkConfig := &network.NetworkingConfig{}
if len(shuffleNetwork) > 0 { if len(shuffleNetwork) > 0 {
log.Printf("Starting worker with network %s", shuffleNetwork)
networkConfig = &network.NetworkingConfig{ networkConfig = &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{ EndpointsConfig: map[string]*network.EndpointSettings{
shuffleNetwork: { shuffleNetwork: {
@@ -139,7 +133,15 @@ func deployWorker(image string, identifier string, env []string) {
}, },
} }
env = append(env, fmt.Sprintf("DOCKER_NETWORK", shuffleNetwork)) env = append(env, fmt.Sprintf("DOCKER_NETWORK=%s", shuffleNetwork))
} else {
log.Printf("Starting worker WITHOUT any specified network: %s", shuffleNetwork)
}
// ROFL: https://docker-py.readthedocs.io/en/1.4.0/volumes/
config := &container.Config{
Image: image,
Env: env,
} }
//test := &network.EndpointSettings{ //test := &network.EndpointSettings{
+7
View File
@@ -1107,6 +1107,13 @@ func main() {
} }
} }
shuffleNetwork := os.Getenv("DOCKER_NETWORK")
if len(shuffleNetwork) > 0 {
log.Printf("Running with Docker network %s", shuffleNetwork)
} else {
log.Printf("No docker network specified for Worker.")
}
// WORKER_TESTING_WORKFLOW should be a workflow ID // WORKER_TESTING_WORKFLOW should be a workflow ID
authorization := "" authorization := ""
executionId := "" executionId := ""