Added basics of cloud sync
This commit is contained in:
+126
-35
@@ -161,6 +161,7 @@ type Environment struct {
|
|||||||
Default bool `datastore:"default" json:"default"`
|
Default bool `datastore:"default" json:"default"`
|
||||||
Archived bool `datastore:"archived" json:"archived"`
|
Archived bool `datastore:"archived" json:"archived"`
|
||||||
Id string `datastore:"id" json:"id"`
|
Id string `datastore:"id" json:"id"`
|
||||||
|
OrgId string `datastore:"org_id" json:"org_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
@@ -1026,7 +1027,7 @@ func handleSetEnvironments(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
var environments []Environment
|
var environments []Environment
|
||||||
q := datastore.NewQuery("Environments")
|
q := datastore.NewQuery("Environments").Filter("org_id =", user.ActiveOrg.Id)
|
||||||
_, err = dbclient.GetAll(ctx, q, &environments)
|
_, err = dbclient.GetAll(ctx, q, &environments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
@@ -1185,6 +1186,19 @@ func createNewUser(username, password, role, apikey string, org Org) error {
|
|||||||
log.Printf("Error adding User %s: %s", username, err)
|
log.Printf("Error adding User %s: %s", username, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
neworg, err := getOrg(ctx, org.Id)
|
||||||
|
if err == nil {
|
||||||
|
log.Printf("Updating org %s with user %s", org.Name, newUser.Username)
|
||||||
|
neworg.Users = append(org.Users, *newUser)
|
||||||
|
err = setOrg(ctx, *neworg, neworg.Id)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed updating org with user %s", newUser.Username)
|
||||||
|
} else {
|
||||||
|
log.Printf("Successfully updated org with user %s!", newUser.Username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// url := fmt.Sprintf("https://shuffler.io/register/%s", verifyToken.String())
|
// url := fmt.Sprintf("https://shuffler.io/register/%s", verifyToken.String())
|
||||||
// const verifyMessage = `
|
// const verifyMessage = `
|
||||||
//Registration URL :)
|
//Registration URL :)
|
||||||
@@ -1253,7 +1267,22 @@ func handleRegister(resp http.ResponseWriter, request *http.Request) {
|
|||||||
role = "admin"
|
role = "admin"
|
||||||
}
|
}
|
||||||
|
|
||||||
err = createNewUser(data.Username, data.Password, role, "", user.ActiveOrg)
|
ctx := context.Background()
|
||||||
|
currentOrg := user.ActiveOrg
|
||||||
|
if user.ActiveOrg.Id == "" {
|
||||||
|
log.Printf("There's no active org for the user. Checking if there's a single one to assing it to.")
|
||||||
|
|
||||||
|
var orgs []Org
|
||||||
|
q := datastore.NewQuery("Organizations")
|
||||||
|
_, err = dbclient.GetAll(ctx, q, &orgs)
|
||||||
|
if err == nil && len(orgs) == 1 {
|
||||||
|
log.Printf("No org exists in auth. Setting to default (first one)")
|
||||||
|
currentOrg = orgs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
err = createNewUser(data.Username, data.Password, role, "", currentOrg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed registering user: %s", err)
|
log.Printf("Failed registering user: %s", err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
@@ -1502,7 +1531,6 @@ func handleUpdateUser(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
||||||
log.Printf("APIGEN!")
|
|
||||||
cors := handleCors(resp, request)
|
cors := handleCors(resp, request)
|
||||||
if cors {
|
if cors {
|
||||||
return
|
return
|
||||||
@@ -1515,7 +1543,6 @@ func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
|||||||
resp.Write([]byte(`{"success": false}`))
|
resp.Write([]byte(`{"success": false}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Printf("APIKEY")
|
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if request.Method == "GET" {
|
if request.Method == "GET" {
|
||||||
@@ -2192,7 +2219,7 @@ func handleGetEnvironments(resp http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := handleApiAuthentication(resp, request)
|
user, err := handleApiAuthentication(resp, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Api authentication failed in set new workflowhandler: %s", err)
|
log.Printf("Api authentication failed in set new workflowhandler: %s", err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
@@ -2202,7 +2229,7 @@ func handleGetEnvironments(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
var environments []Environment
|
var environments []Environment
|
||||||
q := datastore.NewQuery("Environments")
|
q := datastore.NewQuery("Environments").Filter("org_id =", user.ActiveOrg.Id)
|
||||||
_, err = dbclient.GetAll(ctx, q, &environments)
|
_, err = dbclient.GetAll(ctx, q, &environments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
@@ -2299,6 +2326,7 @@ func handleGetUsers(resp http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Check by org.
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
var users []User
|
var users []User
|
||||||
q := datastore.NewQuery("Users")
|
q := datastore.NewQuery("Users")
|
||||||
@@ -6454,6 +6482,14 @@ func runInit(ctx context.Context) {
|
|||||||
log.Printf("Should add %d users to organization default", len(users))
|
log.Printf("Should add %d users to organization default", len(users))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(activeOrgs) == 0 {
|
||||||
|
orgQuery := datastore.NewQuery("Organizations")
|
||||||
|
_, err = dbclient.GetAll(ctx, orgQuery, &activeOrgs)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed getting orgs the second time around")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fix active users etc
|
// Fix active users etc
|
||||||
q := datastore.NewQuery("Users").Filter("active =", true)
|
q := datastore.NewQuery("Users").Filter("active =", true)
|
||||||
var activeusers []User
|
var activeusers []User
|
||||||
@@ -6520,24 +6556,54 @@ func runInit(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//log.Printf("Found %d users.", len(users))
|
log.Printf("Found %d users.", len(users))
|
||||||
|
if len(activeOrgs) == 1 && len(users) > 0 {
|
||||||
|
for _, user := range users {
|
||||||
|
if user.ActiveOrg.Id == "" {
|
||||||
|
user.ActiveOrg = activeOrgs[0]
|
||||||
|
err = setUser(ctx, &user)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed updating user %s", user.Username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
//log.Printf(users[0].Username)
|
//log.Printf(users[0].Username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets environments and inits if it doesn't exist
|
// Gets environments and inits if it doesn't exist
|
||||||
log.Printf("Setting up environments")
|
|
||||||
count, err := getEnvironmentCount()
|
count, err := getEnvironmentCount()
|
||||||
if count == 0 && err == nil {
|
if count == 0 && err == nil && len(activeOrgs) == 1 {
|
||||||
|
log.Printf("Setting up environment with org %s", activeOrgs[0].Id)
|
||||||
item := Environment{
|
item := Environment{
|
||||||
Name: "Shuffle",
|
Name: "Shuffle",
|
||||||
Type: "onprem",
|
Type: "onprem",
|
||||||
|
OrgId: activeOrgs[0].Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = setEnvironment(ctx, &item)
|
err = setEnvironment(ctx, &item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed setting up new environment")
|
log.Printf("Failed setting up new environment")
|
||||||
}
|
}
|
||||||
|
} else if len(activeOrgs) == 1 {
|
||||||
|
log.Printf("Setting up all environments with org %s", activeOrgs[0].Id)
|
||||||
|
var environments []Environment
|
||||||
|
q := datastore.NewQuery("Environments")
|
||||||
|
_, err = dbclient.GetAll(ctx, q, &environments)
|
||||||
|
if err == nil {
|
||||||
|
for _, item := range environments {
|
||||||
|
if item.OrgId == activeOrgs[0].Id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
item.OrgId = activeOrgs[0].Id
|
||||||
|
err = setEnvironment(ctx, &item)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed adding environment to org %s", activeOrgs[0].Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets schedules and starts them
|
// Gets schedules and starts them
|
||||||
@@ -6765,9 +6831,9 @@ func handleCloudSetup(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
log.Printf("Apidata: %s", tmpData.Apikey)
|
log.Printf("Apidata: %s", tmpData.Apikey)
|
||||||
|
|
||||||
|
// FIXME: Path
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
syncPath := "http://192.168.3.6:5002/api/v1/cloud/sync"
|
syncPath := "http://192.168.3.6:5002/api/v1/cloud/sync"
|
||||||
|
|
||||||
type requestStruct struct {
|
type requestStruct struct {
|
||||||
ApiKey string `json:"api_key"`
|
ApiKey string `json:"api_key"`
|
||||||
}
|
}
|
||||||
@@ -6780,7 +6846,7 @@ func handleCloudSetup(resp http.ResponseWriter, request *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed marshaling api key data: %s", err)
|
log.Printf("Failed marshaling api key data: %s", err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed cloud sync."`, err)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed cloud sync."}`, err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6793,49 +6859,74 @@ func handleCloudSetup(resp http.ResponseWriter, request *http.Request) {
|
|||||||
newresp, err := client.Do(req)
|
newresp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeader(400)
|
resp.WriteHeader(400)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed cloud sync: %s"`, err)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed cloud sync: %s. Contact support."}`, err)))
|
||||||
//setBadMemcache(ctx, docPath)
|
//setBadMemcache(ctx, docPath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if newresp.StatusCode != 200 {
|
|
||||||
resp.WriteHeader(400)
|
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Response code %d during sync. Expecting 200."`, newresp.StatusCode)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
respBody, err := ioutil.ReadAll(newresp.Body)
|
respBody, err := ioutil.ReadAll(newresp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeader(500)
|
resp.WriteHeader(500)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Can't parse sync data"`)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Can't parse sync data. Contact support."}`)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type responseStruct struct {
|
type retStruct struct {
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
Reason string `json:"reason"`
|
SyncFeatures SyncFeatures `json:"sync_features"`
|
||||||
|
SessionKey string `json:"session_key"`
|
||||||
|
IntervalSeconds int64 `json:"interval_seconds"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
}
|
}
|
||||||
log.Printf("Respbody: %s", string(respBody))
|
|
||||||
|
|
||||||
responseData := responseStruct{}
|
log.Printf("Respbody: %s", string(respBody))
|
||||||
|
responseData := retStruct{}
|
||||||
err = json.Unmarshal(respBody, &responseData)
|
err = json.Unmarshal(respBody, &responseData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeader(500)
|
resp.WriteHeader(500)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed handling cloud data"`)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed handling cloud data"}`)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if responseData.Success {
|
if newresp.StatusCode != 200 {
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(401)
|
||||||
if len(responseData.Reason) > 0 {
|
resp.Write(respBody)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "%s"}`, responseData.Reason)))
|
return
|
||||||
} else {
|
}
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
|
|
||||||
}
|
if !responseData.Success {
|
||||||
} else {
|
|
||||||
resp.WriteHeader(400)
|
resp.WriteHeader(400)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, responseData.Reason)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, responseData.Reason)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// 1. Set cloudsync for org to be active
|
||||||
|
// 2. Add iterative sync schedule for interval seconds
|
||||||
|
// 3. Add another environment for the org's users
|
||||||
|
org.CloudSync = true
|
||||||
|
org.SyncFeatures = responseData.SyncFeatures
|
||||||
|
|
||||||
|
org.SyncConfig = SyncConfig{
|
||||||
|
Apikey: responseData.SessionKey,
|
||||||
|
Interval: responseData.IntervalSeconds,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = setOrg(ctx, *org, org.Id)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("ERROR: Failed updating org even though there was success: %s", err)
|
||||||
|
resp.WriteHeader(400)
|
||||||
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed setting up org after sync success. Contact support."}`)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if responseData.IntervalSeconds > 0 {
|
||||||
|
// FIXME:
|
||||||
|
log.Printf("Should set up interval for %d with session key %s for org %s", responseData.IntervalSeconds, responseData.SessionKey, org.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteHeader(200)
|
||||||
|
resp.Write(respBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initHandlers() {
|
func initHandlers() {
|
||||||
|
|||||||
@@ -68,16 +68,21 @@ type ExecutionRequest struct {
|
|||||||
|
|
||||||
type SyncFeatures struct {
|
type SyncFeatures struct {
|
||||||
Apps SyncData `json:"apps" datastore:"apps"`
|
Apps SyncData `json:"apps" datastore:"apps"`
|
||||||
Workflows SyncData `json:"apps" datastore:"apps"`
|
Workflows SyncData `json:"workflows" datastore:"workflows"`
|
||||||
Schedules SyncData `json:"apps" datastore:"apps"`
|
Schedules SyncData `json:"schedules" datastore:"schedules"`
|
||||||
Autocomplete SyncData `json:"apps" datastore:"apps"`
|
Autocomplete SyncData `json:"autocomplete" datastore:"autocomplete"`
|
||||||
Authentication SyncData `json:"apps" datastore:"apps"`
|
Authentication SyncData `json:"authentication" datastore:"authentication"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SyncData struct {
|
type SyncData struct {
|
||||||
Active bool `json:"active" datastore:"active"`
|
Active bool `json:"active" datastore:"active"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SyncConfig struct {
|
||||||
|
Interval int64 `json:"interval" datastore:"interval"`
|
||||||
|
Apikey string `json:"api_key" datastore:"api_key"`
|
||||||
|
}
|
||||||
|
|
||||||
// Role is just used for feedback for a user
|
// Role is just used for feedback for a user
|
||||||
type Org struct {
|
type Org struct {
|
||||||
Name string `json:"name" datastore:"name"`
|
Name string `json:"name" datastore:"name"`
|
||||||
@@ -87,6 +92,7 @@ type Org struct {
|
|||||||
Role string `json:"role" datastore:"role"`
|
Role string `json:"role" datastore:"role"`
|
||||||
Roles []string `json:"roles" datastore:"roles"`
|
Roles []string `json:"roles" datastore:"roles"`
|
||||||
CloudSync bool `json:"cloud_sync" datastore:"CloudSync"`
|
CloudSync bool `json:"cloud_sync" datastore:"CloudSync"`
|
||||||
|
SyncConfig SyncConfig `json:"sync_config" datastore:"sync_config"`
|
||||||
SyncFeatures SyncFeatures `json:"sync_features" datastore:"sync_features"`
|
SyncFeatures SyncFeatures `json:"sync_features" datastore:"sync_features"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+101
-20
@@ -3,24 +3,36 @@ 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 FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
import Switch from '@material-ui/core/Switch';
|
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 Divider from '@material-ui/core/Divider';
|
import Divider from '@material-ui/core/Divider';
|
||||||
import TextField from '@material-ui/core/TextField';
|
import TextField from '@material-ui/core/TextField';
|
||||||
import ListItem from '@material-ui/core/ListItem';
|
|
||||||
import Button from '@material-ui/core/Button';
|
import Button from '@material-ui/core/Button';
|
||||||
import Tabs from '@material-ui/core/Tabs';
|
import Tabs from '@material-ui/core/Tabs';
|
||||||
import Tab from '@material-ui/core/Tab';
|
import Tab from '@material-ui/core/Tab';
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import List from '@material-ui/core/List';
|
||||||
|
import ListItem from '@material-ui/core/ListItem';
|
||||||
import ListItemText from '@material-ui/core/ListItemText';
|
import ListItemText from '@material-ui/core/ListItemText';
|
||||||
|
import ListItemAvatar from '@material-ui/core/ListItemAvatar';
|
||||||
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
|
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
|
||||||
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
|
import Avatar from '@material-ui/core/Avatar';
|
||||||
|
|
||||||
|
|
||||||
import { useAlert } from "react-alert";
|
import { useAlert } from "react-alert";
|
||||||
|
|
||||||
import { Dialog, DialogTitle, DialogActions, DialogContent } from '@material-ui/core';
|
import { Dialog, DialogTitle, DialogActions, DialogContent } from '@material-ui/core';
|
||||||
import { useTheme } from '@material-ui/core/styles';
|
import { useTheme } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
import PolymerIcon from '@material-ui/icons/Polymer';
|
||||||
|
import CheckCircleIcon from '@material-ui/icons/CheckCircle';
|
||||||
|
import CloseIcon from '@material-ui/icons/Close';
|
||||||
|
import AppsIcon from '@material-ui/icons/Apps';
|
||||||
|
import ImageIcon from '@material-ui/icons/Image';
|
||||||
|
import DeleteIcon from '@material-ui/icons/Delete';
|
||||||
import CachedIcon from '@material-ui/icons/Cached';
|
import CachedIcon from '@material-ui/icons/Cached';
|
||||||
import AccessibilityNewIcon from '@material-ui/icons/AccessibilityNew';
|
import AccessibilityNewIcon from '@material-ui/icons/AccessibilityNew';
|
||||||
import LockIcon from '@material-ui/icons/Lock';
|
import LockIcon from '@material-ui/icons/Lock';
|
||||||
@@ -46,6 +58,8 @@ const Admin = (props) => {
|
|||||||
const [curTab, setCurTab] = React.useState(0);
|
const [curTab, setCurTab] = React.useState(0);
|
||||||
const [users, setUsers] = React.useState([]);
|
const [users, setUsers] = React.useState([]);
|
||||||
const [organizations, setOrganizations] = React.useState([]);
|
const [organizations, setOrganizations] = React.useState([]);
|
||||||
|
const [orgSyncResponse, setOrgSyncResponse] = React.useState("");
|
||||||
|
|
||||||
const [environments, setEnvironments] = React.useState([]);
|
const [environments, setEnvironments] = React.useState([]);
|
||||||
const [authentication, setAuthentication] = React.useState([]);
|
const [authentication, setAuthentication] = React.useState([]);
|
||||||
const [schedules, setSchedules] = React.useState([])
|
const [schedules, setSchedules] = React.useState([])
|
||||||
@@ -183,6 +197,8 @@ const Admin = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const enableCloudSync = (apikey, organization) => {
|
const enableCloudSync = (apikey, organization) => {
|
||||||
|
setOrgSyncResponse("")
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
apikey: apikey,
|
apikey: apikey,
|
||||||
organization: organization,
|
organization: organization,
|
||||||
@@ -200,21 +216,32 @@ const Admin = (props) => {
|
|||||||
'Content-Type': 'application/json; charset=utf-8',
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(response =>
|
.then(response => {
|
||||||
response.json().then(responseJson => {
|
setLoading(false)
|
||||||
setLoading(false)
|
if (response.status === 200) {
|
||||||
console.log(responseJson)
|
console.log("Cloud sync success?")
|
||||||
if (responseJson["success"] === false) {
|
} else {
|
||||||
alert.error("Failed setting up cloud sync")
|
console.log("Cloud sync fail?")
|
||||||
} else {
|
}
|
||||||
alert.success("Set up cloud sync!")
|
|
||||||
}
|
return response.json()
|
||||||
}),
|
})
|
||||||
)
|
.then((responseJson) => {
|
||||||
.catch(error => {
|
if (!responseJson.success && responseJson.reason !== undefined) {
|
||||||
setLoading(false)
|
setOrgSyncResponse(responseJson.reason)
|
||||||
alert.error("Err: " + error.toString())
|
alert.error("Failed to sync: "+responseJson.reason)
|
||||||
});
|
} else if (!responseJson.success) {
|
||||||
|
alert.error("Failed to sync.")
|
||||||
|
} else {
|
||||||
|
alert.success("Sync set up!")
|
||||||
|
getOrgs()
|
||||||
|
//setCloudSyncModalOpen(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
setLoading(false)
|
||||||
|
alert.error("Err: " + error.toString())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const onPasswordChange = () => {
|
const onPasswordChange = () => {
|
||||||
@@ -780,6 +807,49 @@ const Admin = (props) => {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
const GridItem = (props) => {
|
||||||
|
const primary = props.data.primary
|
||||||
|
const secondary = props.data.secondary
|
||||||
|
const primaryIcon = props.data.icon
|
||||||
|
const secondaryIcon = props.data.active ?
|
||||||
|
<CheckCircleIcon style={{color: "green"}} />
|
||||||
|
:
|
||||||
|
<CloseIcon style={{color: "red"}} />
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
{primaryIcon}
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={primary}
|
||||||
|
secondary={secondary}
|
||||||
|
/>
|
||||||
|
{secondaryIcon}
|
||||||
|
</ListItem>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemColor = "black"
|
||||||
|
var syncList = [
|
||||||
|
{
|
||||||
|
"primary": "Workflows",
|
||||||
|
"secondary": "",
|
||||||
|
"active": false,
|
||||||
|
"icon": <PolymerIcon style={{color: itemColor}}/>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"primary": "Apps",
|
||||||
|
"secondary": "",
|
||||||
|
"active": false,
|
||||||
|
"icon": <AppsIcon style={{color: itemColor}}/>,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
const cloudSyncModal =
|
const cloudSyncModal =
|
||||||
<Dialog
|
<Dialog
|
||||||
open={cloudSyncModalOpen}
|
open={cloudSyncModalOpen}
|
||||||
@@ -798,8 +868,6 @@ const Admin = (props) => {
|
|||||||
</span></DialogTitle>
|
</span></DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
What does <a href="https://shuffler.io/docs/hybrid#cloud_sync" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>cloud sync</a> do?
|
What does <a href="https://shuffler.io/docs/hybrid#cloud_sync" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>cloud sync</a> do?
|
||||||
<div style={{marginTop: 5}}/>
|
|
||||||
Cloud Apikey
|
|
||||||
<div style={{display: "flex", marginBottom: 20, }}>
|
<div style={{display: "flex", marginBottom: 20, }}>
|
||||||
<TextField
|
<TextField
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -832,7 +900,20 @@ const Admin = (props) => {
|
|||||||
Test sync
|
Test sync
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
{orgSyncResponse.length > 0 ?
|
||||||
|
<Typography style={{marginTop: 5, marginBottom: 10}}>
|
||||||
|
Error: {orgSyncResponse}
|
||||||
|
</Typography>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
|
<Grid container style={{width: "100%", marginBottom: 15, }}>
|
||||||
|
{syncList.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<GridItem data={data} />
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Grid>
|
||||||
* New triggers (userinput, hotmail realtime)<div/>
|
* New triggers (userinput, hotmail realtime)<div/>
|
||||||
* Execute in the cloud rather than onprem<div/>
|
* Execute in the cloud rather than onprem<div/>
|
||||||
* Apps can be built in the cloud<div/>
|
* Apps can be built in the cloud<div/>
|
||||||
@@ -1301,7 +1382,7 @@ const Admin = (props) => {
|
|||||||
style={{minWidth: 150, maxWidth: 150}}
|
style={{minWidth: 150, maxWidth: 150}}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
{environments === undefined ? null : environments.map((environment, index)=> {
|
{environments === undefined || environments === null ? null : environments.map((environment, index)=> {
|
||||||
if (!showArchived && environment.archived) {
|
if (!showArchived && environment.archived) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user