[ActionEditor] Support for action save/input events.

This commit is contained in:
Fabio Manganiello 2023-12-16 14:13:11 +01:00
parent f9ba4564e7
commit 7fcffe899e
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="action-editor-container" @click="onClick"> <div class="action-editor-container" :class="{'with-save': withSave}" @click="onClick">
<Loading v-if="loading" /> <Loading v-if="loading" />
<!-- Action executor container --> <!-- Action executor container -->
@ -14,17 +14,29 @@
</div> </div>
<!-- Execute panel views --> <!-- Execute panel views -->
<Tabs> <div class="header-container">
<Tab :selected="structuredInput" icon-class="fas fa-list" @input="onInputTypeChange(true)"> <div class="tabs-container">
Structured <Tabs>
</Tab> <Tab :selected="structuredInput" icon-class="fas fa-list" @input="onInputTypeChange(true)">
Structured
</Tab>
<Tab :selected="!structuredInput" icon-class="fas fa-code" @input="onInputTypeChange(false)"> <Tab :selected="!structuredInput" icon-class="fas fa-code" @input="onInputTypeChange(false)">
Raw Raw
</Tab> </Tab>
</Tabs> </Tabs>
</div>
<form ref="actionForm" autocomplete="off" @submit.prevent="executeAction"> <div class="buttons" v-if="withSave">
<button type="submit" class="save-btn btn-primary"
:disabled="running || !isValidAction" title="Save"
@click.stop="onSubmit">
<i class="fas fa-save" />
</button>
</div>
</div>
<form ref="actionForm" autocomplete="off" @submit.prevent="onSubmit">
<!-- Structured request container --> <!-- Structured request container -->
<div class="request structured" v-if="structuredInput"> <div class="request structured" v-if="structuredInput">
<!-- Request header --> <!-- Request header -->
@ -40,10 +52,9 @@
autofocus autofocus
:disabled="running" :disabled="running"
:value="action.name" /> :value="action.name" />
</div>
<div class="buttons"> <button :type="withSave ? 'button' : 'submit'" class="run-btn btn-primary"
<button type="submit" class="run-btn btn-primary" :disabled="running || !isValidAction" title="Run" @click.stop="executeAction">
:disabled="running || !action?.name?.length" title="Run">
<i class="fas fa-play" /> <i class="fas fa-play" />
</button> </button>
</div> </div>
@ -88,7 +99,8 @@
<label> <label>
<textarea v-model="rawRequest" ref="rawAction" :placeholder="rawRequestPlaceholder" /> <textarea v-model="rawRequest" ref="rawAction" :placeholder="rawRequestPlaceholder" />
</label> </label>
<button type="submit" :disabled="running" class="run-btn btn-primary" title="Run"> <button :type="withSave ? 'button' : 'submit'" :disabled="running"
class="raw-run-btn btn-primary" title="Run" @click.stop="executeAction">
<i class="fas fa-play" /> <i class="fas fa-play" />
</button> </button>
</div> </div>
@ -133,6 +145,11 @@ export default {
value: { value: {
type: Object, type: Object,
}, },
withSave: {
type: Boolean,
default: false,
},
}, },
data() { data() {
@ -167,6 +184,14 @@ export default {
return this.action?.doc_url return this.action?.doc_url
}, },
isValidAction() {
return (
this.action?.name?.length &&
this.action.name in this.actions &&
Object.values(this.action.args).every((arg) => !arg.required || arg.value?.length)
)
},
autocompleteItems() { autocompleteItems() {
if (this.getPluginName(this.action.name) in this.plugins) { if (this.getPluginName(this.action.name) in this.plugins) {
return Object.keys(this.actions).sort() return Object.keys(this.actions).sort()
@ -407,6 +432,9 @@ export default {
this.actionInput.focus() this.actionInput.focus()
} else { } else {
this.$refs.rawAction.focus() this.$refs.rawAction.focus()
if (this.isValidAction) {
this.rawRequest = JSON.stringify(this.toRequest(this.action), null, 2)
}
} }
}) })
}, },
@ -456,6 +484,22 @@ export default {
} }
}, },
toRequest(action) {
return {
type: 'request',
action: action.name,
args: this.requestArgs,
}
},
emitInput(value) {
value = value || this.value
if (!value)
return
this.$emit("input", this.toRequest(value))
},
onClick(event) { onClick(event) {
// Intercept any clicks from RST rendered links and open them in a new tab // Intercept any clicks from RST rendered links and open them in a new tab
if (event.target.tagName.toLowerCase() === 'a') { if (event.target.tagName.toLowerCase() === 'a') {
@ -479,6 +523,17 @@ export default {
}) })
}) })
}, },
onSubmit() {
if (!this.isValidAction)
return
if (this.withSave) {
this.emitInput(this.action)
} else {
this.executeAction()
}
},
}, },
watch: { watch: {
@ -500,6 +555,8 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
@import "common"; @import "common";
$btn-width: 3.5em;
.action-editor-container { .action-editor-container {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -522,14 +579,19 @@ export default {
} }
.run-btn { .run-btn {
width: $btn-width;
height: 2.5em;
background: $background-color; background: $background-color;
border-radius: .25em; border-color: $border-color-3;
padding: .5em 1.5em; border-left: none;
box-shadow: $primary-btn-shadow; border-radius: 0 1em 1em 0;
padding: .5em 1em;
box-shadow: none;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: $hover-bg; background: $hover-bg;
border-color: $active-glow-bg-2;
box-shadow: none; box-shadow: none;
} }
@ -546,6 +608,11 @@ export default {
} }
} }
.raw-run-btn {
padding: .5em 1.5em;
border-radius: 1em;
}
.curl-modal-container { .curl-modal-container {
:deep(.modal) { :deep(.modal) {
.content { .content {
@ -561,5 +628,88 @@ export default {
} }
} }
} }
.autocomplete-container {
display: flex;
flex-direction: row;
align-items: center;
:deep(.autocomplete) {
width: calc(100% - $btn-width);
input[type=text] {
height: 2.5em;
border-radius: 1em 0 0 1em;
box-shadow: none;
}
}
}
.raw-request {
height: 100%;
overflow: auto;
textarea {
width: 100%;
min-height: 15em;
border: $default-border-2;
box-shadow: $border-shadow-bottom;
padding: 1em;
font-family: monospace;
font-size: 0.9em;
}
}
&.with-save {
.header-container {
width: 100%;
height: $tab-height;
display: flex;
flex-direction: row;
background: $tabs-bg;
border-bottom: 1px solid $border-color-3;
box-shadow: $border-shadow-bottom;
.buttons {
width: $btn-width;
height: calc($tab-height - 1px);
background: $tab-bg;
button {
width: $btn-width;
height: $tab-height;
&:disabled {
opacity: 0.7;
background: $default-bg-6;
cursor: initial;
box-shadow: none;
&:hover {
background: $tab-bg;
box-shadow: none;
}
}
}
}
.tabs-container {
width: calc(100% - $btn-width);
:deep(.tabs) {
width: 100%;
height: calc($tab-height - 1px);
box-shadow: none;
@include until($tablet) {
.tab {
width: 50%;
flex-grow: 0;
}
}
}
}
}
}
} }
</style> </style>