orchestrator refactor, user creation block

This commit is contained in:
Martin McKeaveney 2020-05-30 13:41:46 +01:00
parent 7d871ff9cf
commit 65d0161007
11 changed files with 91 additions and 75 deletions

View File

@ -1,6 +1,6 @@
import mustache from "mustache"
// TODO: tidy up import
import blockDefinitions from "../../../pages/[application]/workflow/WorkflowPanel/blockDefinitions"
import blockDefinitions from "../../../components/workflow/WorkflowPanel/blockDefinitions"
import { generate } from "shortid"
/**
@ -79,7 +79,7 @@ export default class Workflow {
type: block.type,
params: block.params,
args,
heading: definition.actionId,
heading: block.actionId,
body: mustache.render(tagline, args),
})

View File

@ -1,31 +1,31 @@
import { isString } from "lodash/fp"
// import { isString } from "lodash/fp"
import {
BB_STATE_BINDINGPATH,
BB_STATE_FALLBACK,
BB_STATE_BINDINGSOURCE,
isBound,
parseBinding,
} from "@budibase/client/src/state/parseBinding"
// import {
// BB_STATE_BINDINGPATH,
// BB_STATE_FALLBACK,
// BB_STATE_BINDINGSOURCE,
// isBound,
// parseBinding,
// } from "@budibase/client/src/state/parseBinding"
export const isBinding = isBound
// export const isBinding = isBound
export const setBinding = ({ path, fallback, source }, binding = {}) => {
if (isNonEmptyString(path)) binding[BB_STATE_BINDINGPATH] = path
if (isNonEmptyString(fallback)) binding[BB_STATE_FALLBACK] = fallback
binding[BB_STATE_BINDINGSOURCE] = source || "store"
return binding
}
// export const setBinding = ({ path, fallback, source }, binding = {}) => {
// if (isNonEmptyString(path)) binding[BB_STATE_BINDINGPATH] = path
// if (isNonEmptyString(fallback)) binding[BB_STATE_FALLBACK] = fallback
// binding[BB_STATE_BINDINGSOURCE] = source || "store"
// return binding
// }
export const getBinding = val => {
const binding = parseBinding(val)
return binding
? binding
: {
path: "",
source: "store",
fallback: "",
}
}
// export const getBinding = val => {
// const binding = parseBinding(val)
// return binding
// ? binding
// : {
// path: "",
// source: "store",
// fallback: "",
// }
// }
const isNonEmptyString = s => isString(s) && s.length > 0
// const isNonEmptyString = s => isString(s) && s.length > 0

View File

@ -43,13 +43,6 @@
)
}
async function selectRecord(record) {
return await api.loadRecord(record.key, {
appname: $store.appname,
instanceId: $backendUiStore.selectedDatabase._id,
})
}
const ITEMS_PER_PAGE = 10
// Internal headers we want to hide from the user
const INTERNAL_HEADERS = ["_id", "_rev", "modelId", "type"]

View File

@ -2,8 +2,7 @@
import { backendUiStore } from "builderStore"
import IconButton from "../common/IconButton.svelte"
import Input from "../common/Input.svelte"
import PropertyCascader from "./PropertyCascader"
import { isBinding, getBinding, setBinding } from "../common/binding"
// import PropertyCascader from "./PropertyCascader"
import Colorpicker from "../common/Colorpicker.svelte"
export let value = ""
@ -50,7 +49,7 @@
{/each}
</select>
{:else}
<PropertyCascader {onChanged} {value} />
<!-- <PropertyCascader {onChanged} {value} /> -->
{/if}
</div>

View File

@ -5,6 +5,8 @@
let params
console.log("wfblock", workflowBlock)
$: workflowParams = workflowBlock.params
? Object.entries(workflowBlock.params)
: []
@ -13,7 +15,7 @@
</script>
<label class="uk-form-label">
{workflowBlock.type}: {workflowBlock.heading}
{workflowBlock.type}: {workflowBlock.actionId}
</label>
{#each workflowParams as [parameter, type]}
<div class="uk-margin block-field">
@ -27,6 +29,18 @@
<option value={option}>{option}</option>
{/each}
</select>
{:else if type === 'accessLevel'}
<select
class="budibase__input"
bind:value={workflowBlock.args[parameter]}>
<option value="ADMIN">Admin</option>
<option value="POWER_USER">Power User</option>
</select>
{:else if type === 'password'}
<input
type="password"
class="budibase__input"
bind:value={workflowBlock.args[parameter]} />
{:else if type === 'number'}
<input
type="number"

View File

@ -49,13 +49,14 @@ const ACTION = {
},
CREATE_USER: {
description: "Create a new user.",
tagline: "Create user <b>{{username}}</b>",
icon: "ri-user-add-fill",
name: "Create User",
environment: "SERVER",
params: {
name: "string",
username: "string",
password: "password",
accessLevel: "accessLevel",
accessLevelId: "accessLevel",
},
},
SEND_EMAIL: {

View File

@ -1,5 +1,7 @@
import get from "lodash/fp/get"
import { get } from "svelte/store";
import { setState } from "../../state/setState";
import mustache from "mustache";
import { appStore } from "../../state/store";
/**
* The workflow orchestrator is a class responsible for executing workflows.
@ -15,25 +17,21 @@ export default class Orchestrator {
}
set strategy(strategy) {
this._strategy = strategy
this._strategy = strategy({ api: this.api, instanceId: this.instanceId });
}
async execute(workflowId) {
const EXECUTE_WORKFLOW_URL = `/api/${this.instanceId}/workflows/${workflowId}`
const workflow = await this.api.get({ url: EXECUTE_WORKFLOW_URL })
this._strategy.run({
workflow: workflow.definition,
api: this.api,
instanceId: this.instanceId,
})
this._strategy.run(workflow.definition)
}
}
// Execute a workflow from a running budibase app
export const clientStrategy = {
export const clientStrategy = ({ api, instanceId }) => ({
delay: ms => new Promise(resolve => setTimeout(resolve, ms)),
context: {},
bindContextArgs: function(args, api) {
bindContextArgs: function(args) {
const mappedArgs = { ...args }
console.log("original args", args)
@ -42,35 +40,18 @@ export const clientStrategy = {
for (let arg in args) {
const argValue = args[arg]
// Means that it's bound to state or workflow context
console.log(argValue, get(appStore));
mappedArgs[arg] = mustache.render(argValue, {
context: this.context,
// TODO: map to the real state
state: {}
state: get(appStore)
});
}
// if (argValue.startsWith("$")) {
// // if value is bound to workflow context.
// if (argValue.startsWith("$context")) {
// const path = argValue.replace("$context.", "")
// // pass in the value from context
// mappedArgs[arg] = get(path, this.context)
// }
// // if the value is bound to state
// if (argValue.startsWith("$state")) {
// const path = argValue.replace("$state.", "")
// // pass in the value from state
// // TODO: not working
// mappedArgs[arg] = api.getState(path)
// }
// }
// }
console.log(mappedArgs)
return Object.values(mappedArgs)
return mappedArgs
},
run: async function({ workflow, api, instanceId }) {
run: async function(workflow) {
const block = workflow.next
console.log("Executing workflow block", block)
@ -81,7 +62,7 @@ export const clientStrategy = {
if (block.environment === "CLIENT") {
if (block.actionId === "SET_STATE") {
// get props from the workflow context if required
api.setState(...this.bindContextArgs(block.args))
setState(...Object.values(this.bindContextArgs(block.args)))
// update the context with the data
this.context = {
...this.context,
@ -135,7 +116,6 @@ export const clientStrategy = {
console.log("workflowContext", this.context)
// TODO: clean this up, don't pass all those args
await this.run({ workflow: workflow.next, instanceId, api })
await this.run(workflow.next)
},
}
})

View File

@ -1,5 +1,6 @@
import regexparam from "regexparam"
import { routerStore } from "../state/store";
import { initRouteStore } from "../state/store"
// TODO: refactor
export const screenRouter = ({ screens, onScreenSelected, appRootPath }) => {

View File

@ -0,0 +1,26 @@
const userController = require("../../user")
module.exports = async function createUser(user) {
console.log("SAVING this user", user)
const ctx = {
params: {
instanceId: "inst_60dd510_700f7dc06735403e81d5af91072d7241",
},
request: {
body: user
},
}
try {
const response = await userController.create(ctx)
return {
user: response
}
} catch (err) {
console.error(err);
return {
user: null
}
}
}

View File

@ -2,9 +2,11 @@ const viewController = require("../api/controllers/view")
const modelController = require("../api/controllers/model")
const workflowController = require("../api/controllers/workflow")
// Access Level IDs
const ADMIN_LEVEL_ID = "ADMIN"
const POWERUSER_LEVEL_ID = "POWER_USER"
// Permissions
const READ_MODEL = "read-model"
const WRITE_MODEL = "write-model"
const READ_VIEW = "read-view"