diff --git a/src/renderer/components/nodes/EditorNodeAction.vue b/src/renderer/components/nodes/EditorNodeAction.vue index aa13e96..f59c01f 100644 --- a/src/renderer/components/nodes/EditorNodeAction.vue +++ b/src/renderer/components/nodes/EditorNodeAction.vue @@ -3,38 +3,57 @@
- +
@@ -100,13 +119,16 @@ import DOMPurify from 'dompurify' import { makeResolvedParams } from '@renderer/utils/evaluator' import { ValidationError } from '@renderer/models/error' import AddNodeButton from '../AddNodeButton.vue' -import { useElementHover } from '@vueuse/core' const props = defineProps({ value: { type: Object as PropType, required: true }, + index: { + type: Number, + required: true + }, path: { type: Array as PropType, required: true @@ -130,7 +152,17 @@ const $node = ref() // const isHovered = useElementHover($node) const editor = useEditor() -const { getNodeDefinition, setBlockValue, addNode, getPluginDefinition, removeNode } = editor +const { + getNodeDefinition, + setBlockValue, + addNode, + getPluginDefinition, + removeNode, + swapNodes, + cloneNode, + disableNode, + enableNode, +} = editor const { activeNode } = storeToRefs(editor) const nodeDefinition = computed(() => { @@ -141,7 +173,6 @@ const pluginDefinition = computed(() => { return getPluginDefinition(value.value.origin.pluginId) }) - const onValueChanged = (newValue: unknown, paramKey: string) => { setBlockValue(value.value.uid, { ...value.value, @@ -207,7 +238,7 @@ watchDebounced( const showSidebar = ref(false) - diff --git a/src/renderer/pages/editor.vue b/src/renderer/pages/editor.vue index 0c30140..6dcacd0 100644 --- a/src/renderer/pages/editor.vue +++ b/src/renderer/pages/editor.vue @@ -225,20 +225,21 @@ const run = async () => { const { setActiveNode } = instance setIsRunning(true) - await processGraph({ - graph: klona(nodes.value), - definitions: pluginDefinitions.value, - variables: variables.value, - context: {}, - steps: {}, - onNodeEnter: (node) => { - setActiveNode(node) - }, - onNodeExit: () => { - setActiveNode() - }, - onExecuteItem: async (node, params, steps) => { - /* if (node.type === 'condition') { + try { + await processGraph({ + graph: klona(nodes.value), + definitions: pluginDefinitions.value, + variables: variables.value, + context: {}, + steps: {}, + onNodeEnter: (node) => { + setActiveNode(node) + }, + onNodeExit: () => { + setActiveNode() + }, + onExecuteItem: async (node, params, steps) => { + /* if (node.type === 'condition') { return api.execute('condition:execute', { nodeId: node.origin.nodeId, pluginId: node.origin.pluginId, @@ -246,26 +247,36 @@ const run = async () => { steps }) } else */ if (node.type === 'action') { - const result = await api.execute('action:execute', { - nodeId: node.origin.nodeId, - pluginId: node.origin.pluginId, - params, - steps - }) - return result - } else { - throw new Error('Unhandled type ' + node.type) + const result = await api.execute('action:execute', { + nodeId: node.origin.nodeId, + pluginId: node.origin.pluginId, + params, + steps + }) + return result + } else { + throw new Error('Unhandled type ' + node.type) + } } - } - }) + }) + + toast.add({ + summary: 'Execution done', + life: 10_000, + severity: 'success', + detail: 'Your project has been executed successfully' + }) + } catch (e) { + console.error('error while executing process') + + toast.add({ + summary: 'Execution failed', + life: 10_000, + severity: 'error', + detail: 'Project has encountered an error' + }) + } setIsRunning(false) - - toast.add({ - summary: 'Execution done', - life: 10_000, - severity: 'success', - detail: 'Your project has been executed successfully' - }) } const isSaving = ref(false) diff --git a/src/renderer/pages/nodes-editor.vue b/src/renderer/pages/nodes-editor.vue index 42d31bc..62631c6 100644 --- a/src/renderer/pages/nodes-editor.vue +++ b/src/renderer/pages/nodes-editor.vue @@ -8,6 +8,7 @@ v-if="node.type === 'action'" :path="[...path, (startingIndex + index).toString()]" :value="node" + :index="index" :steps="steps" :errors="errors[node.uid]" > @@ -116,6 +117,3 @@ const { nodes, path } = toRefs(props) color: #333; } -isConditionDefinition, isEventDefinition, isLoopDefinition, , BlockCondition, BlockEvent, -BlockLoopimport { nanoid } from 'nanoid' isConditionDefinition, isEventDefinition, isLoopDefinition, -, BlockCondition, BlockEvent, BlockLoop diff --git a/src/renderer/store/editor.ts b/src/renderer/store/editor.ts index b1681c1..2d054ca 100644 --- a/src/renderer/store/editor.ts +++ b/src/renderer/store/editor.ts @@ -1,8 +1,7 @@ -import { computed, ref, toRaw, watch } from 'vue' +import { computed, ref, toRaw } from 'vue' import { Block, BlockAction, - BlockComment, BlockCondition, BlockEvent, BlockLoop, @@ -10,17 +9,7 @@ import { savedFileMigrator, Steps } from '@@/model' -import { useAPI } from '@renderer/composables/api' -import { - Action, - Condition, - RendererPluginDefinition, - Event, - Loop, - CynNode, - InputDefinition, - RendererNodeDefinition -} from '@cyn/plugin-core' +import { Action, Condition, Event, Loop, CynNode, RendererNodeDefinition } from '@cyn/plugin-core' import { Variable } from '@cyn/core-app' import { defineStore, storeToRefs } from 'pinia' import get from 'get-value' @@ -28,13 +17,14 @@ import set from 'set-value' import { nanoid } from 'nanoid' import { AddNodeEvent, AddTriggerEvent } from '@renderer/components/AddNodeButton.model' import { useAppStore } from './app' -import { SaveLocation } from '@@/save-location' -import { FileRepo, useFiles } from './files' +import { useFiles } from './files' import { useRouteParams } from '@vueuse/router' import { ValidationError } from '@renderer/models/error' import { isRequired } from '@@/validation' import { processGraph } from '@@/graph' import { useLogger } from '@@/logger' +import { klona } from 'klona' +import { create } from 'mutative' export type Context = Record @@ -344,6 +334,46 @@ export const useEditor = defineStore('editor', () => { } } + const swapNodes = (index: number, direction: 'up' | 'down') => { + const newIndex = index + (direction === 'up' ? -1 : 1) + const output = blocks.value.map((element, _index) => + _index === index + ? blocks.value[newIndex] + : _index === newIndex + ? blocks.value[index] + : element + ) + console.log('input', blocks.value) + console.log('output', output) + + blocks.value = output + } + + const cloneNode = (node: Block, newIndex: number) => { + const newNode = klona(node) + addNodeToBlock(newNode, [], newIndex) + } + + const disableNode = (node: Block) => { + blocks.value = create(klona(blocks.value), (draft) => { + for (let i = 0; i < draft.length; i += 1) { + if (draft[i].uid === node.uid) { + draft[i].disabled = true + } + } + }) + } + + const enableNode = (node: Block) => { + blocks.value = create(klona(blocks.value), (draft) => { + for (let i = 0; i < draft.length; i += 1) { + if (draft[i].uid === node.uid) { + draft[i].disabled = false + } + } + }) + } + const addNode = (event: AddNodeEvent) => { const { node: nodeDefinition, path, plugin: pluginDefinition, insertAt } = event @@ -529,7 +559,12 @@ export const useEditor = defineStore('editor', () => { processGraph, loadPreset, isRunning, - setIsRunning + setIsRunning, + + swapNodes, + cloneNode, + disableNode, + enableNode } }) diff --git a/src/renderer/utils/fmt.ts b/src/renderer/utils/fmt.ts index 5be5c57..c005dbd 100644 --- a/src/renderer/utils/fmt.ts +++ b/src/renderer/utils/fmt.ts @@ -1,5 +1,5 @@ export const fmt = { param: (value: string, variant?: 'primary' | 'secondary' | undefined) => { - return `
${value}
` + return `
${value}
` } } diff --git a/src/shared/graph.ts b/src/shared/graph.ts index d94774f..b8e6444 100644 --- a/src/shared/graph.ts +++ b/src/shared/graph.ts @@ -68,6 +68,13 @@ export const processGraph = async (options: { } options.onNodeExit(rawNode) } else */ if (rawNode.type === 'action') { + if (rawNode.disabled === true) { + console.warn( + `Node ${rawNode.uid} (${rawNode.origin.pluginId}::${rawNode.origin.nodeId}) is disabled` + ) + continue + } + options.onNodeEnter(rawNode) const newParams = await makeResolvedParams({ diff --git a/src/shared/model.ts b/src/shared/model.ts index e6701f8..f9361c4 100644 --- a/src/shared/model.ts +++ b/src/shared/model.ts @@ -3,7 +3,7 @@ import { WithId } from './utils' import { SaveLocation } from './save-location' import { Simplify } from 'type-fest' import { createMigration, createMigrator, finalVersion, initialVersion } from './libs/migration' -import { any, array, custom, GenericSchema, InferOutput, lazy, literal, object, record, string, union, variant } from 'valibot' +import { any, array, boolean, custom, GenericSchema, InferOutput, lazy, literal, object, optional, record, string, union, variant } from 'valibot' import type { OmitVersion } from './libs/migration/models/migration' export type NodeId = string @@ -23,6 +23,7 @@ export type Origin = InferOutput const BlockActionValidator = object({ type: literal('action'), uid: string(), + disabled: optional(boolean()), params: record(string(), any()), origin: OriginValidator })