fix: render states & transition by fetching workflow data

This commit is contained in:
Shariq Ansari 2023-05-02 17:55:46 +05:30
parent b004a28a15
commit f258ca09ac
7 changed files with 132 additions and 38 deletions

View file

@ -52,8 +52,13 @@ onConnect(edge => {
const action_node = {
id: "action-" + frappe.utils.get_random(5),
type: "action",
label: "Approve",
position: { x: center_x, y: center_y }
position: { x: center_x, y: center_y },
data: {
action: "",
allowed: "All",
from: source_node.data.state,
to: target_node.data.state
},
};
addNodes([action_node]);
@ -130,8 +135,12 @@ function onDrop(event) {
const new_state = {
id: state_id,
type: "state",
label: "Open",
position,
data: {
state: "",
doc_status: "0",
allow_edit: "All"
}
};
addNodes([new_state]);
@ -162,11 +171,7 @@ function onDragStart(event) {
}
onPaneReady(() => fitView({ padding: 0.4 }));
onMounted(() => {
setTimeout(() => {
store.setup_undo_redo();
}, 1000);
});
onMounted(() => store.fetch());
</script>
<template>

View file

@ -22,7 +22,7 @@ const isValidConnection = ({ source, target }) => {
<template>
<div class="node" tabindex="0">
<div v-if="node.label" class="node-label">{{ node.label }}</div>
<div v-if="node.data.action" class="node-label">{{ node.data.action }}</div>
<div v-else class="node-placeholder text-muted">{{ __("No Label") }}</div>
<Handle
v-for="handle in ['top', 'right', 'bottom', 'left']"

View file

@ -22,7 +22,7 @@ const isValidConnection = ({ source, target }) => {
<template>
<div class="node" tabindex="0">
<div v-if="node.label" class="node-label">{{ node.label }}</div>
<div v-if="node.data.state" class="node-label">{{ node.data.state }}</div>
<div v-else class="node-placeholder text-muted">{{ __("No Label") }}</div>
<Handle
v-for="handle in ['top', 'right', 'bottom', 'left']"

View file

@ -1,37 +1,32 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { get_workflow_elements } from "./utils";
import { useManualRefHistory, onKeyDown } from "@vueuse/core";
export const useStore = defineStore("workflow-builder-store", () => {
let workflow_name = ref(null);
let workflow_doc = ref(null);
let workflow = ref({
elements: [
{ id: "1", label: "Open", type: "state", position: { x: 300, y: 150 } },
{ id: "2", label: "Approved", type: "state", position: { x: 700, y: 150 } },
{ id: "action-1", label: "Approve", type: "action", position: { x: 500, y: 170 } },
{
id: "edge-1-action-1",
source: "1",
target: "action-1",
type: "transition",
sourceHandle: "right",
targetHandle: "left",
updatable: true,
animated: true,
},
{
id: "edge-action-1-2",
source: "action-1",
target: "2",
type: "transition",
sourceHandle: "right",
targetHandle: "left",
updatable: true,
animated: true,
},
],
elements: [],
});
let ref_history = ref(null);
async function fetch() {
await frappe.model.clear_doc("Workflow", workflow_name.value);
await frappe.model.with_doc("Workflow", workflow_name.value);
workflow_doc.value = frappe.get_doc("Workflow", workflow_name.value);
await frappe.model.with_doctype(workflow_doc.value.document_type);
workflow.value.elements = get_workflow_elements(workflow_doc.value);
setup_undo_redo();
}
function reset_changes() {
fetch();
}
let undo_redo_keyboard_event = onKeyDown(true, (e) => {
if (!ref_history.value) return;
if (e.ctrlKey || e.metaKey) {
@ -50,8 +45,11 @@ export const useStore = defineStore("workflow-builder-store", () => {
}
return {
workflow_name,
workflow,
ref_history,
fetch,
reset_changes,
setup_undo_redo,
};
});

View file

@ -0,0 +1,79 @@
export function get_workflow_elements(workflow) {
let elements = [];
let states = {};
let x = 150;
let y = 100;
function state_obj(id, data) {
let state = {
id: id.toString(),
type: "state",
position: { x: x, y: y },
data: data,
};
if (!states[data.state]) {
states[data.state] = [id, { x: x, y: y }];
}
return state;
}
function action_obj(id, data, position) {
return {
id: "action-" + id,
type: "action",
position: position,
data: data,
};
}
function transition_obj(id, source, target) {
return {
id: "edge-" + id,
type: "transition",
source: source.toString(),
target: target.toString(),
sourceHandle: "right",
targetHandle: "left",
updatable: true,
animated: true,
};
}
workflow.states.forEach((state, i) => {
x += 400;
elements.push(
state_obj(i + 1, {
state: state.state,
doc_status: state.doc_status,
allow_edit: state.allow_edit,
update_field: state.update_field,
update_value: state.update_value,
is_optional_state: state.is_optional_state,
next_action_email_template: state.next_action_email_template,
message: state.message,
})
);
});
workflow.transitions.forEach((transition, i) => {
let source = states[transition.state];
let target = states[transition.next_state];
let position = { x: source[1].x + 250, y: y + 20 };
let data = {
from: transition.state,
to: transition.next_state,
action: transition.action,
allowed: transition.allowed,
allow_self_approval: transition.allow_self_approval,
condition: transition.condition,
};
let action = "action-" + (i + 1);
elements.push(action_obj(i + 1, data, position));
elements.push(transition_obj(source[0] + "-" + action, source[0], action));
elements.push(transition_obj(action + "-" + target[0], action, target[0]));
});
return elements;
}

View file

@ -28,6 +28,10 @@ class WorkflowBuilder {
SetVueGlobals(app);
app.use(pinia);
// create a store
this.store = useStore();
this.store.workflow_name = this.workflow;
// mount the app
this.$workflow_builder = app.mount(this.$wrapper.get(0));
}

View file

@ -17,7 +17,8 @@
"states",
"transition_rules",
"transitions",
"workflow_state_field"
"workflow_state_field",
"workflow_data"
],
"fields": [
{
@ -92,12 +93,18 @@
"fieldtype": "Data",
"label": "Workflow State Field",
"reqd": 1
},
{
"fieldname": "workflow_data",
"fieldtype": "JSON",
"hidden": 1,
"label": "Workflow Data"
}
],
"icon": "fa fa-random",
"idx": 1,
"links": [],
"modified": "2023-05-01 13:21:30.951859",
"modified": "2023-05-02 16:56:28.704844",
"modified_by": "Administrator",
"module": "Workflow",
"name": "Workflow",
@ -117,5 +124,6 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "ASC",
"states": [],
"track_changes": 1
}
}