workflow charts

This commit is contained in:
Martin McKeaveney 2020-05-22 16:32:23 +01:00
parent e659e69e86
commit cacee947bf
14 changed files with 146 additions and 60 deletions

View File

@ -18,10 +18,12 @@ const post = apiCall("POST")
const get = apiCall("GET")
const patch = apiCall("PATCH")
const del = apiCall("DELETE")
const put = apiCall("PUT")
export default {
post,
get,
patch,
delete: del,
put
}

View File

@ -1,6 +1,46 @@
import { writable } from "svelte/store"
import api from "../api"
const workflowActions = store => ({
fetch: async instanceId => {
const WORKFLOWS_URL = `/api/${instanceId}/workflows`;
const workflowResponse = await api.get(WORKFLOWS_URL);
const json = await workflowResponse.json();
store.update(state => {
state.workflows = json
return state
})
},
create: async ({ instanceId, name }) => {
const workflow = { name }
const CREATE_WORKFLOW_URL = `/api/${instanceId}/workflows`;
const response = await api.post(CREATE_WORKFLOW_URL, workflow)
const json = await response.json();
store.update(state => {
state.workflows = state.workflows.concat(json.workflow)
state.selectedWorkflowId = json.workflow._id
return state
})
},
update: async ({ instanceId, workflow }) => {
const UPDATE_WORKFLOW_URL = `/api/${instanceId}/workflows`;
const response = await api.put(UPDATE_WORKFLOW_URL, workflow)
const json = await response.json();
store.update(state => {
const existingIdx = state.workflows.findIndex(existing => existing._id === workflow._id);
state.workflows.splice(existingIdx, 1, json.workflow);
state.workflows = state.workflows
return state
})
},
select: workflow => {
store.update(state => {
state.selectedWorkflowId = workflow._id
return state;
})
}
});
export const getWorkflowStore = () => {
const INITIAL_WORKFLOW_STATE = {
workflows: []
@ -8,27 +48,7 @@ export const getWorkflowStore = () => {
const store = writable(INITIAL_WORKFLOW_STATE)
store.actions = {
fetch: async instanceId => {
const WORKFLOWS_URL = `/api/${instanceId}/workflows`;
const workflowResponse = await api.get(WORKFLOWS_URL);
const json = await workflowResponse.json();
store.update(state => {
state.workflows = json
return state
})
},
create: async ({ instanceId, name }) => {
const workflow = { name }
const CREATE_WORKFLOW_URL = `/api/${instanceId}/workflows`;
const response = await api.post(CREATE_WORKFLOW_URL, workflow)
const json = await response.json();
store.update(state => {
state.workflows = state.workflows.concat(json.workflow)
return state
})
},
}
store.actions = workflowActions(store);
return store
}

View File

@ -293,6 +293,7 @@ body, html {
.grabme, .blockico {
display: inline-block;
}
.grabme {
margin-top: 10px;
margin-left: 10px;
@ -322,6 +323,12 @@ body, html {
text-align: center;
white-space: nowrap;
}
.blockico i {
font-size: 24px;
color: var(--dark-grey);
}
.blockico span {
height: 100%;
width: 0px;

View File

@ -42,19 +42,18 @@
</div>
<div id="blocklist">
{#each definitions as blockDefinition}
<div class="blockelem create-flowy noselect">
<div
class="blockelem create-flowy noselect"
data-name={blockDefinition.name}
>
<input
type="hidden"
name="blockelemtype"
class="blockelemtype"
value="1" />
<div class="grabme">
<!-- <img src="assets/grabme.svg" /> -->
</div>
<div class="blockin">
<div class="blockico">
<span />
<!-- <img src="assets/eye.svg" /> -->
<i class={blockDefinition.icon} />
</div>
<div class="blocktext">
<p class="blocktitle">{blockDefinition.name}</p>

View File

@ -7,44 +7,55 @@ const ACTIONS = {
},
NAVIGATE: {
name: "Navigate",
icon: "",
icon: "ri-navigation-line",
description: "Navigate to another page.",
type: "CLIENT"
},
CREATE_RECORD: {
SAVE_RECORD: {
name: "Save Record",
icon: "",
icon: "ri-save-3-fill",
description: "Save a record to your database.",
type: "SERVER",
},
DELETE_RECORD: {
description: "Delete a record from your database.",
icon: "",
icon: "ri-delete-bin-line",
name: "Delete Record",
type: "SERVER",
}
};
const TRIGGERS = {
SAVE_RECORD: {
name: "Record Saved",
icon: "ri-delete-bin-line",
description: "Save a record to your database.",
type: "SERVER",
},
CLICK: {
name: "Click",
icon: "",
icon: "ri-cursor-line",
description: "Trigger when you click on an element in the UI."
},
LOAD: {
name: "Load",
icon: "",
icon: "ri-loader-line",
description: "Trigger an element has finished loading."
},
INPUT: {
name: "Input",
icon: "",
icon: "ri-text",
description: "Trigger when you type into an input box."
},
};
const UTILITIES = {
IFELSE: {
name: "If/Else",
icon: "ri-git-branch-line",
description: "Perform different actions based on a condition",
type: "CLIENT"
},
}
export default {

View File

@ -16,6 +16,7 @@
name,
instanceId,
})
flowy.deleteBlocks();
onClosed()
}
</script>

View File

@ -1,10 +1,9 @@
<script>
import Modal from "svelte-simple-modal"
import { onMount, getContext } from "svelte"
import { backendUiStore, workflowStore } from "builderStore";
import { backendUiStore, workflowStore } from "builderStore"
import api from "builderStore/api"
import CreateWorkflowModal from "./CreateWorkflowModal.svelte";
import CreateWorkflowModal from "./CreateWorkflowModal.svelte"
const { open, close } = getContext("simple-modal")
@ -19,7 +18,7 @@
}
onMount(() => {
workflowStore.actions.fetch($backendUiStore.selectedDatabase._id);
workflowStore.actions.fetch($backendUiStore.selectedDatabase._id)
})
</script>
@ -30,7 +29,10 @@
</header>
<ul>
{#each $workflowStore.workflows as workflow}
<li class="workflow-item">
<li
class="workflow-item"
class:selected={workflow._id === $workflowStore.selectedWorkflowId}
on:click={() => workflowStore.actions.select(workflow)}>
<i class="ri-stackshare-line" />
{workflow.name}
</li>
@ -71,7 +73,7 @@
border-radius: 3px;
height: 40px;
}
.workflow-item i {
font-size: 24px;
margin-right: 10px;
@ -81,4 +83,8 @@
cursor: pointer;
background: var(--secondary);
}
.workflow-item.selected {
background: var(--secondary);
}
</style>

View File

@ -1,6 +1,7 @@
<script>
import { workflowStore } from "builderStore"
import { WorkflowList } from "./WorkflowList"
import { BlockPanel } from "./BlockPanel";
import { BlockPanel } from "./BlockPanel"
</script>
<div class="root">
@ -11,7 +12,9 @@
<slot />
</div>
<div class="nav">
<BlockPanel />
{#if $workflowStore.selectedWorkflowId}
<BlockPanel />
{/if}
</div>
</div>

View File

@ -1,25 +1,31 @@
<script>
import { onMount } from "svelte"
export let workflow = {}
import { workflowStore, backendUiStore } from "builderStore";
import api from "builderStore/api";
let canvas
let workflow
let instanceId = $backendUiStore.selectedDatabase._id;
$: workflow = $workflowStore.workflows.find(wf => wf._id === $workflowStore.selectedWorkflowId)
// $: if (workflow && workflow.uiTree) flowy.import(workflow.uiTree);
onMount(() => {
if (workflow.uiTree) {
flowy.import(workflow.uiTree);
return;
}
flowy(canvas, onGrab, onRelease, onSnap);
});
flowy(canvas, onGrab, onRelease);
})
function onGrab() {
function onGrab(block) {
console.log(block);
}
function onSnap(block, first, parent){
workflow.uiTree = flowy.output();
workflowStore.actions.update({ instanceId, workflow })
return true;
}
function onRelease() {
console.log("RELEASED!")
}
// function onGrab(block) {

View File

@ -15,8 +15,6 @@ export {
DatatableCell,
DatatableRow,
} from "./Datatable"
export { default as indexDatatable } from "./Templates/indexDatatable"
export { default as recordForm } from "./Templates/recordForm"
export { List, ListItem } from "./List"
export { Menu } from "./Menu"
export { Select } from "./Select"

View File

@ -28,7 +28,7 @@
"test:watch": "jest -w",
"initialise": "node ../cli/bin/budi init -b local -q",
"budi": "node ../cli/bin/budi",
"dev:builder": "nodemon ../cli/bin/budi run",
"dev:builder": "node ../cli/bin/budi run",
"electron": "electron src/electron.js",
"build:electron": "electron-builder --dir",
"publish:electron": "electron-builder -mwl --publish always",

View File

@ -38,14 +38,28 @@ exports.create = async function(ctx) {
message: "Workflow created successfully",
workflow: {
...workflow,
...response
_rev: response.rev,
_id: response.id
}
};
}
exports.update = async function(ctx) {
const db = new CouchDB(ctx.params.instanceId)
ctx.body = await db.get(ctx.params.recordId)
const workflow = ctx.request.body;
const response = await db.put(workflow)
workflow._rev = response.rev
ctx.status = 200
ctx.body = {
message: `Workflow ${workflow._id} updated successfully.`,
workflow: {
...workflow,
_rev: response.rev,
_id: response.id
},
}
}
exports.fetch = async function(ctx) {

View File

@ -73,6 +73,25 @@ describe("/workflows", () => {
})
})
describe("update", () => {
it("updates a workflows data", async () => {
await createWorkflow();
workflow._id = workflow.id
workflow._rev = workflow.rev
workflow.name = "Updated Name";
const res = await request
.put(`/api/${instance._id}/workflows`)
.set(defaultHeaders)
.send(workflow)
.expect('Content-Type', /json/)
.expect(200)
expect(res.body.message).toEqual("Workflow Test Workflow updated successfully.");
expect(res.body.workflow.name).toEqual("Updated Name");
})
})
describe("fetch", () => {
it("return all the workflows for an instance", async () => {
await createWorkflow();

View File

@ -7,7 +7,7 @@ router
.get("/api/:instanceId/workflows", controller.fetch)
.get("/api/:instanceId/workflows/:id", controller.find)
.post("/api/:instanceId/workflows", controller.create)
.put("/api/:instanceId/workflows/:id", controller.update)
.put("/api/:instanceId/workflows", controller.update)
.delete("/api/:instanceId/workflows/:id/:rev", controller.destroy)
module.exports = router