Added `ProcedureEditor` component.

This commit is contained in:
Fabio Manganiello 2023-12-16 19:03:46 +01:00
parent 07a144aadc
commit d4543c2fb7
Signed by: blacklight
GPG Key ID: D90FBA7F76362774
1 changed files with 213 additions and 0 deletions

View File

@ -0,0 +1,213 @@
<template>
<div class="procedure-editor-container"
:class="{dragging: dragItem != null}">
<div class="procedure-editor">
<form autocomplete="off" @submit.prevent="executeAction">
<div class="name-editor-container" v-if="withName">
<div class="row item">
<div class="name">
<label>
<i class="icon fas fa-pen-to-square" />
Name
</label>
</div>
<div class="value">
<input type="text" v-model="newValue.name" />
</div>
</div>
</div>
<div class="actions">
<div class="row item" v-for="(action, index) in newValue.actions" :key="index">
<div class="drop-target-container"
:class="{active: dropIndex === index}"
v-if="dragItem != null && dragItem > index"
@dragover.prevent="dropIndex = index"
@dragenter.prevent="dropIndex = index"
@dragleave.prevent="dropIndex = undefined"
@dragend.prevent="dropIndex = undefined"
@drop="onDrop(index)">
<div class="drop-target" />
</div>
<div class="separator" v-else-if="dragItem != null && dragItem === index" />
<ActionTile :value="action"
draggable with-delete
@drag="dragItem = index"
@drop="dragItem = undefined"
@input="newValue.actions[index] = $event"
@delete="newValue.actions.splice(index, 1)" />
<div class="drop-target-container"
:class="{active: dropIndex === index}"
@dragover.prevent="dropIndex = index"
@dragenter.prevent="dropIndex = index"
@dragleave.prevent="dropIndex = undefined"
@dragend.prevent="dropIndex = undefined"
@drop="onDrop(index)"
v-if="dragItem != null && dragItem < index">
<div class="drop-target" />
</div>
<div class="separator" v-else-if="dragItem != null && dragItem === index" />
</div>
<div class="row item">
<ActionTile :value="newAction" @input="newValue.actions.push($event)" />
</div>
</div>
<!-- Structured response container -->
<Response :response="response" :error="error" />
</form>
</div>
</div>
</template>
<script>
import ActionTile from "@/components/Action/ActionTile"
import Response from "@/components/Action/Response"
import Utils from "@/Utils"
export default {
mixins: [Utils],
emits: ['input'],
components: {
ActionTile,
Response,
},
props: {
withName: {
type: Boolean,
default: false,
},
value: {
type: Object,
default: () => ({
name: undefined,
actions: [],
}),
},
},
data() {
return {
loading: false,
running: false,
response: undefined,
error: undefined,
actions: [],
newValue: {...this.value},
newAction: {},
dragItem: undefined,
dropIndex: undefined,
}
},
methods: {
onResponse(response) {
this.response = (
typeof response === 'string' ? response : JSON.stringify(response, null, 2)
).trim()
this.error = undefined
},
onError(error) {
this.response = undefined
this.error = error
},
onDone() {
this.running = false
},
onDrop(index) {
if (this.dragItem === undefined)
return
this.newValue.actions.splice(
index, 0, this.newValue.actions.splice(this.dragItem, 1)[0]
)
},
executeAction() {
if (!this.value.actions?.length)
return
this.running = true
this.execute(this.value.actions).then(this.onResponse).catch(this.onError).finally(this.onDone)
},
},
watch: {
value: {
immediate: true,
deep: true,
handler(value) {
this.newValue = {...value}
},
},
},
}
</script>
<style lang="scss" scoped>
.procedure-editor-container {
display: flex;
flex-direction: column;
padding-top: 0.75em;
.procedure-editor {
width: 100%;
}
.actions {
.item {
margin-bottom: 0.75em;
}
.drop-target-container {
width: 100%;
height: 0.75em;
display: flex;
align-items: center;
&.active {
.drop-target {
height: 0.5em;
background: $tile-bg;
border: none;
opacity: 0.75;
}
}
.drop-target {
width: 100%;
height: 2px;
border: 1px solid $default-fg-2;
border-radius: 0.25em;
padding: 0 0.5em;
}
}
}
&.dragging {
padding-top: 0;
.actions {
.item {
margin-bottom: 0;
}
.separator {
height: 0.75em;
}
}
}
}
</style>