workflow charts
This commit is contained in:
parent
e659e69e86
commit
cacee947bf
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
name,
|
||||
instanceId,
|
||||
})
|
||||
flowy.deleteBlocks();
|
||||
onClosed()
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue