284 lines
6.5 KiB
Svelte
284 lines
6.5 KiB
Svelte
<script lang="ts">
|
||
import { createEventDispatcher, getContext } from 'svelte'
|
||
import type { FlowEditorContext } from '../flows/types'
|
||
import { emptyFlowModuleState } from '../flows/utils'
|
||
import {
|
||
clickButtonBySelector,
|
||
triggerAddFlowStep,
|
||
selectFlowStepKind,
|
||
updateFlowModuleById
|
||
} from './utils'
|
||
import Tutorial from './Tutorial.svelte'
|
||
import { updateProgress } from '$lib/tutorialUtils'
|
||
import { nextId } from '../flows/flowModuleNextId'
|
||
|
||
const dispatch = createEventDispatcher()
|
||
const { flowStore, selectedId, flowStateStore } =
|
||
getContext<FlowEditorContext>('FlowEditorContext')
|
||
|
||
let tutorial: Tutorial | undefined = undefined
|
||
|
||
export function runTutorial(indexToInsertAt?: number | undefined) {
|
||
tutorial?.runTutorial({ indexToInsertAt })
|
||
}
|
||
</script>
|
||
|
||
<Tutorial
|
||
bind:this={tutorial}
|
||
index={1}
|
||
name="forloop"
|
||
tainted={false}
|
||
on:error
|
||
on:skipAll
|
||
getSteps={(driver, options) => {
|
||
const id = nextId($flowStateStore, $flowStore)
|
||
const index = options?.indexToInsertAt ?? $flowStore.value.modules.length
|
||
const isFirst = id === 'a'
|
||
|
||
let tempId = ''
|
||
|
||
return [
|
||
{
|
||
popover: {
|
||
title: 'For loops tutorial',
|
||
description:
|
||
'Learn how to build our first for loop to iterate on. You can use arrow keys to navigate.'
|
||
}
|
||
},
|
||
|
||
{
|
||
element: `#flow-editor-add-step-${index}`,
|
||
popover: {
|
||
title: 'Add a step',
|
||
description: 'Click here to add a step to your flow',
|
||
onNextClick: () => {
|
||
triggerAddFlowStep(index)
|
||
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
})
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
popover: {
|
||
title: 'Steps kind',
|
||
description: "Choose the kind of step you want to add. Let's start with a simple action"
|
||
},
|
||
element: '#flow-editor-insert-module'
|
||
},
|
||
|
||
{
|
||
popover: {
|
||
title: 'Insert loop',
|
||
description: "Let's pick forloop",
|
||
onNextClick: () => {
|
||
selectFlowStepKind(isFirst ? 4 : 3)
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
})
|
||
}
|
||
},
|
||
element: `#flow-editor-insert-module > div > button:nth-child(${isFirst ? 4 : 3})`
|
||
},
|
||
|
||
{
|
||
element: '#flow-editor-iterator-expression',
|
||
popover: {
|
||
title: 'Iterator expression',
|
||
description:
|
||
'The iterator expression is a javascript expression that respresents the array to iterate on. Here we will iterate on the firstname input letter by letter',
|
||
onNextClick: () => {
|
||
updateFlowModuleById($flowStore, id, (module) => {
|
||
if (module.value.type === 'forloopflow') {
|
||
if (module.value.iterator.type === 'javascript') {
|
||
module.value.iterator.expr = '[1,2,3]'
|
||
}
|
||
}
|
||
})
|
||
|
||
dispatch('reload')
|
||
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
})
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
element: '#flow-editor-iterator-expression',
|
||
popover: {
|
||
title: 'Iterator expression',
|
||
description:
|
||
'We can refer to the result of previous steps using the results object: results.a or use static values like [1,2,3] in this case.',
|
||
onNextClick: () => {
|
||
updateFlowModuleById($flowStore, id, (module) => {
|
||
const newId = nextId($flowStateStore, $flowStore)
|
||
tempId = newId
|
||
|
||
if (module.value.type === 'forloopflow') {
|
||
module.value.modules = [
|
||
{
|
||
id: newId,
|
||
value: {
|
||
type: 'rawscript',
|
||
content: 'def main(x):\n return x',
|
||
// @ts-ignore
|
||
language: 'python3',
|
||
input_transforms: {
|
||
x: {
|
||
type: 'javascript',
|
||
// @ts-ignore
|
||
value: '',
|
||
expr: ''
|
||
}
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
|
||
$flowStateStore[newId] = emptyFlowModuleState()
|
||
|
||
$flowStateStore[newId].schema.properties = {
|
||
x: {
|
||
type: 'string',
|
||
description: '',
|
||
default: null
|
||
}
|
||
}
|
||
})
|
||
|
||
dispatch('reload')
|
||
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
})
|
||
}
|
||
}
|
||
},
|
||
{
|
||
popover: {
|
||
title: 'Step of the loop',
|
||
description: 'We added an action to the loop. Let’s configure it',
|
||
onNextClick: () => {
|
||
$selectedId = tempId
|
||
$flowStore = $flowStore
|
||
|
||
dispatch('reload')
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
})
|
||
}
|
||
}
|
||
},
|
||
{
|
||
element: '#flow-editor-editor',
|
||
popover: {
|
||
title: 'Python step',
|
||
description:
|
||
'We can write python code in the editor. In this example we will capitalize the letter'
|
||
}
|
||
},
|
||
|
||
{
|
||
element: '#flow-editor-step-input',
|
||
popover: {
|
||
title: 'Flow inputs',
|
||
description: 'UI is autogenerated from your code.'
|
||
}
|
||
},
|
||
{
|
||
element: '#flow-editor-plug',
|
||
popover: {
|
||
title: 'Input configuration',
|
||
description: 'Let’s connect the input to the letter input',
|
||
onNextClick: () => {
|
||
clickButtonBySelector('#flow-editor-plug')
|
||
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
})
|
||
}
|
||
}
|
||
},
|
||
{
|
||
element: '.key',
|
||
popover: {
|
||
title: 'Connect',
|
||
description: 'As we did before, we can connect to the iterator of the loop',
|
||
onNextClick: () => {
|
||
updateFlowModuleById($flowStore, id, (module) => {
|
||
if (
|
||
module.value.type === 'forloopflow' &&
|
||
module.value.modules[0].value.type === 'rawscript'
|
||
) {
|
||
module.value.modules[0].value.input_transforms = {
|
||
x: {
|
||
type: 'javascript',
|
||
expr: 'flow_input.iter.value'
|
||
}
|
||
}
|
||
}
|
||
})
|
||
|
||
dispatch('reload')
|
||
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
})
|
||
}
|
||
}
|
||
},
|
||
{
|
||
element: '#flow-editor-step-input',
|
||
popover: {
|
||
title: 'Iterator',
|
||
description:
|
||
'Loops expose an iterator object that contains the current value of the loop and the index',
|
||
onNextClick: () => {
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
|
||
updateProgress(1)
|
||
})
|
||
}
|
||
}
|
||
},
|
||
{
|
||
element: '#flow-editor-test-flow',
|
||
popover: {
|
||
title: 'Test your flow',
|
||
description: 'We can now test our flow',
|
||
onNextClick: () => {
|
||
clickButtonBySelector('#flow-editor-test-flow')
|
||
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
})
|
||
}
|
||
}
|
||
},
|
||
|
||
{
|
||
element: '#flow-editor-test-flow-drawer',
|
||
popover: {
|
||
title: 'Test your flow',
|
||
description: 'Finally we can test our flow, and view the results!',
|
||
onNextClick: () => {
|
||
clickButtonBySelector('#flow-editor-test-flow-drawer')
|
||
|
||
setTimeout(() => {
|
||
driver.moveNext()
|
||
|
||
updateProgress(0)
|
||
})
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}}
|
||
/>
|