2021-02-20 23:12:54 +01:00
|
|
|
<template>
|
|
|
|
<div class="row plugin execute-container">
|
|
|
|
<Loading v-if="loading" />
|
|
|
|
<div class="command-container">
|
|
|
|
<div class="title">Execute Action</div>
|
|
|
|
<form class="action-form" ref="actionForm" autocomplete="off" @submit.prevent="executeAction">
|
|
|
|
<div class="request-type-container">
|
|
|
|
<input type="radio" id="action-structured-input"
|
|
|
|
:checked="structuredInput" @change="onInputTypeChange(true)">
|
|
|
|
<label for="action-structured-input">Structured request</label>
|
|
|
|
<input type="radio" id="action-raw-input"
|
|
|
|
:checked="!structuredInput" @change="onInputTypeChange(false)">
|
|
|
|
<label for="action-raw-input">Raw request</label>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="request structured-request" :class="structuredInput ? '' : 'hidden'">
|
|
|
|
<div class="autocomplete">
|
|
|
|
<label>
|
|
|
|
<input ref="actionName" type="text" class="action-name"
|
|
|
|
placeholder="Action Name" :disabled="running" v-model="action.name"
|
|
|
|
@change="actionChanged=true" @blur="updateAction">
|
|
|
|
</label>
|
|
|
|
</div>
|
2023-05-17 10:41:02 +02:00
|
|
|
<button type="submit" class="run-btn btn-primary"
|
|
|
|
:disabled="running || !action?.name?.length" title="Run">
|
2021-02-20 23:12:54 +01:00
|
|
|
<i class="fas fa-play" />
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<div class="doc-container" v-if="selectedDoc">
|
|
|
|
<div class="title">
|
|
|
|
Action documentation
|
|
|
|
</div>
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
<div class="doc html">
|
|
|
|
<Loading v-if="docLoading" />
|
|
|
|
<span v-html="selectedDoc" v-else />
|
|
|
|
</div>
|
2021-02-20 23:12:54 +01:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="options" v-if="action.name in actions && (Object.keys(action.args).length ||
|
|
|
|
action.supportsExtraArgs)">
|
|
|
|
<div class="params" ref="params"
|
|
|
|
v-if="Object.keys(action.args).length || action.supportsExtraArgs">
|
|
|
|
<div class="param" :key="name" v-for="name in Object.keys(action.args)">
|
|
|
|
<label>
|
|
|
|
<input type="text" class="action-param-value" :disabled="running"
|
|
|
|
:placeholder="name" v-model="action.args[name].value"
|
|
|
|
@focus="selectAttrDoc(name)"
|
|
|
|
@blur="resetAttrDoc">
|
|
|
|
</label>
|
|
|
|
|
|
|
|
<div class="attr-doc-container mobile" v-if="selectedAttrDoc && selectedAttr === name">
|
|
|
|
<div class="title">
|
|
|
|
Attribute: <div class="attr-name" v-text="selectedAttr" />
|
|
|
|
</div>
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
<div class="doc html">
|
|
|
|
<Loading v-if="docLoading" />
|
|
|
|
<span v-html="selectedAttrDoc" v-else />
|
|
|
|
</div>
|
2021-02-20 23:12:54 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="extra-params" ref="extraParams" v-if="Object.keys(action.extraArgs).length">
|
|
|
|
<div class="param extra-param" :key="i" v-for="i in Object.keys(action.extraArgs)">
|
|
|
|
<label class="col-5">
|
|
|
|
<input type="text" class="action-extra-param-name" :disabled="running"
|
|
|
|
placeholder="Name" v-model="action.extraArgs[i].name">
|
|
|
|
</label>
|
2023-05-17 10:41:02 +02:00
|
|
|
<label class="col-6">
|
2021-02-20 23:12:54 +01:00
|
|
|
<input type="text" class="action-extra-param-value" :disabled="running"
|
|
|
|
placeholder="Value" v-model="action.extraArgs[i].value">
|
|
|
|
</label>
|
2023-05-17 10:41:02 +02:00
|
|
|
<label class="col-1 buttons">
|
2021-02-20 23:12:54 +01:00
|
|
|
<button type="button" class="action-extra-param-del" title="Remove parameter"
|
|
|
|
@click="removeParameter(i)">
|
|
|
|
<i class="fas fa-trash" />
|
|
|
|
</button>
|
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="add-param" v-if="action.supportsExtraArgs">
|
|
|
|
<button type="button" title="Add a parameter" @click="addParameter">
|
|
|
|
<i class="fas fa-plus" />
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="attr-doc-container widescreen" v-if="selectedAttrDoc">
|
|
|
|
<div class="title">
|
|
|
|
Attribute: <div class="attr-name" v-text="selectedAttr" />
|
|
|
|
</div>
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
<div class="doc html">
|
|
|
|
<Loading v-if="docLoading" />
|
|
|
|
<span v-html="selectedAttrDoc" v-else />
|
|
|
|
</div>
|
2021-02-20 23:12:54 +01:00
|
|
|
</div>
|
2023-05-14 15:06:34 +02:00
|
|
|
</div>
|
2021-02-20 23:12:54 +01:00
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
<div class="output-container">
|
|
|
|
<div class="title" v-text="error != null ? 'Error' : 'Output'" v-if="error != null || response != null" />
|
|
|
|
<div class="response" v-html="response" v-if="response != null" />
|
|
|
|
<div class="error" v-html="error" v-else-if="error != null" />
|
2021-02-20 23:12:54 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="request raw-request" :class="structuredInput ? 'hidden' : ''">
|
|
|
|
<div class="first-row">
|
|
|
|
<label>
|
2023-05-17 10:41:02 +02:00
|
|
|
<textarea v-model="rawRequest" ref="rawAction" :placeholder="rawRequestPlaceholder" />
|
2021-02-20 23:12:54 +01:00
|
|
|
</label>
|
|
|
|
<button type="submit" :disabled="running" class="run-btn btn-primary" title="Run">
|
|
|
|
<i class="fas fa-play" />
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="output-container" v-if="response != null || error != null">
|
|
|
|
<div class="title" v-text="error != null ? 'Error' : 'Output'" />
|
|
|
|
<div class="error" v-html="error" v-if="error != null" />
|
|
|
|
<div class="response" v-html="response" v-else-if="response != null" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="procedures-container">
|
|
|
|
<div class="title">Execute Procedure</div>
|
|
|
|
<div class="procedure" :class="selectedProcedure.name === name ? 'selected' : ''"
|
|
|
|
v-for="name in Object.keys(procedures).sort()" :key="name" @click="updateProcedure(name, $event)">
|
|
|
|
<form ref="procedureForm" autocomplete="off" @submit.prevent="executeProcedure">
|
|
|
|
<div class="head">
|
|
|
|
<div class="name col-no-margin-11" v-text="name" />
|
|
|
|
<div class="btn-container col-no-margin-1">
|
|
|
|
<button type="submit" class="run-btn btn-default" :disabled="running" title="Run"
|
|
|
|
@click.stop="$emit('submit')" v-if="selectedProcedure.name === name">
|
|
|
|
<i class="fas fa-play" />
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="params" v-if="selectedProcedure.name === name">
|
|
|
|
<div class="param"
|
|
|
|
v-for="argname in Object.keys(selectedProcedure.args)"
|
|
|
|
:key="argname">
|
|
|
|
<label>
|
|
|
|
<input type="text" class="action-param-value" @click="$event.stopPropagation()" :disabled="running"
|
|
|
|
:placeholder="argname" v-model="selectedProcedure.args[argname]">
|
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import autocomplete from "@/components/elements/Autocomplete"
|
|
|
|
import Utils from "@/Utils"
|
|
|
|
import Loading from "@/components/Loading";
|
|
|
|
|
|
|
|
export default {
|
|
|
|
name: "Execute",
|
|
|
|
components: {Loading},
|
|
|
|
mixins: [Utils],
|
|
|
|
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
loading: false,
|
|
|
|
running: false,
|
2023-05-14 15:06:34 +02:00
|
|
|
docLoading: false,
|
2021-02-20 23:12:54 +01:00
|
|
|
structuredInput: true,
|
|
|
|
actionChanged: false,
|
|
|
|
selectedDoc: undefined,
|
|
|
|
selectedAttr: undefined,
|
|
|
|
selectedAttrDoc: undefined,
|
|
|
|
selectedProcedure: {
|
|
|
|
name: undefined,
|
|
|
|
args: {},
|
|
|
|
},
|
|
|
|
|
|
|
|
response: undefined,
|
|
|
|
error: undefined,
|
|
|
|
rawRequest: undefined,
|
2023-05-17 10:41:02 +02:00
|
|
|
rawRequestPlaceholder: 'Raw JSON request. Example:\n\n' +
|
|
|
|
'{"type": "request", "action": "file.list", "args": {"path": "/"}}',
|
2021-02-20 23:12:54 +01:00
|
|
|
actions: {},
|
|
|
|
plugins: {},
|
|
|
|
procedures: {},
|
2023-05-14 15:06:34 +02:00
|
|
|
actionDocsCache: {},
|
2021-02-20 23:12:54 +01:00
|
|
|
action: {
|
|
|
|
name: undefined,
|
|
|
|
args: {},
|
|
|
|
extraArgs: [],
|
|
|
|
supportsExtraArgs: false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
async refresh() {
|
|
|
|
this.loading = true
|
|
|
|
|
|
|
|
try {
|
|
|
|
this.procedures = await this.request('inspect.get_procedures')
|
2023-05-14 15:06:34 +02:00
|
|
|
this.plugins = await this.request('inspect.get_all_plugins')
|
2021-02-20 23:12:54 +01:00
|
|
|
} finally {
|
|
|
|
this.loading = false
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const plugin of Object.values(this.plugins)) {
|
|
|
|
for (const action of Object.values(plugin.actions)) {
|
|
|
|
action.name = plugin.name + '.' + action.name
|
|
|
|
action.supportsExtraArgs = !!action.has_kwargs
|
|
|
|
delete action.has_kwargs
|
|
|
|
this.actions[action.name] = action
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const self = this
|
2023-05-14 15:06:34 +02:00
|
|
|
autocomplete(this.$refs.actionName, Object.keys(this.actions).sort(), (_, value) => {
|
2021-02-20 23:12:54 +01:00
|
|
|
this.action.name = value
|
|
|
|
self.updateAction()
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
async updateAction() {
|
2021-02-20 23:12:54 +01:00
|
|
|
if (!(this.action.name in this.actions))
|
|
|
|
this.selectedDoc = undefined
|
|
|
|
|
|
|
|
if (!this.actionChanged || !(this.action.name in this.actions))
|
|
|
|
return
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
this.docLoading = true
|
2021-02-20 23:12:54 +01:00
|
|
|
try {
|
|
|
|
this.action = {
|
|
|
|
...this.actions[this.action.name],
|
|
|
|
args: Object.entries(this.actions[this.action.name].args).reduce((args, entry) => {
|
|
|
|
args[entry[0]] = {
|
|
|
|
...entry[1],
|
|
|
|
value: entry[1].default,
|
|
|
|
}
|
|
|
|
|
|
|
|
return args
|
|
|
|
}, {}),
|
|
|
|
extraArgs: [],
|
|
|
|
}
|
|
|
|
} finally {
|
2023-05-14 15:06:34 +02:00
|
|
|
this.docLoading = false
|
2021-02-20 23:12:54 +01:00
|
|
|
}
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
this.selectedDoc =
|
|
|
|
this.actionDocsCache[this.action.name]?.html ||
|
|
|
|
await this.parseDoc(this.action.doc)
|
|
|
|
|
|
|
|
if (!this.actionDocsCache[this.action.name])
|
|
|
|
this.actionDocsCache[this.action.name] = {}
|
|
|
|
this.actionDocsCache[this.action.name].html = this.selectedDoc
|
|
|
|
|
2021-02-20 23:12:54 +01:00
|
|
|
this.actionChanged = false
|
|
|
|
this.response = undefined
|
|
|
|
this.error = undefined
|
|
|
|
},
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
async parseDoc(docString) {
|
|
|
|
if (!docString?.length)
|
2021-02-20 23:12:54 +01:00
|
|
|
return docString
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
return await this.request('utils.rst_to_html', {text: docString})
|
2021-02-20 23:12:54 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
updateProcedure(name, event) {
|
|
|
|
if (event.target.getAttribute('type') === 'submit') {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.selectedProcedure.name === name) {
|
|
|
|
this.selectedProcedure = {
|
|
|
|
name: undefined,
|
|
|
|
args: {},
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(name in this.procedures)) {
|
|
|
|
console.warn('Procedure not found: ' + name)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
this.selectedProcedure = {
|
|
|
|
name: name,
|
|
|
|
args: (this.procedures[name].args || []).reduce((args, arg) => {
|
|
|
|
args[arg] = undefined
|
|
|
|
return args
|
|
|
|
}, {})
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
addParameter() {
|
|
|
|
this.action.extraArgs.push({
|
|
|
|
name: undefined,
|
|
|
|
value: undefined,
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
removeParameter(i) {
|
|
|
|
this.action.extraArgs.pop(i)
|
|
|
|
},
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
async selectAttrDoc(name) {
|
2021-02-20 23:12:54 +01:00
|
|
|
this.selectedAttr = name
|
2023-05-14 15:06:34 +02:00
|
|
|
this.selectedAttrDoc =
|
|
|
|
this.actionDocsCache[this.action.name]?.[name]?.html ||
|
|
|
|
await this.parseDoc(this.action.args[name].doc)
|
|
|
|
|
|
|
|
if (!this.actionDocsCache[this.action.name])
|
|
|
|
this.actionDocsCache[this.action.name] = {}
|
|
|
|
|
|
|
|
this.actionDocsCache[this.action.name][name] = {html: this.selectedAttrDoc}
|
2021-02-20 23:12:54 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
resetAttrDoc() {
|
|
|
|
this.response = undefined
|
|
|
|
this.error = undefined
|
|
|
|
this.selectedAttr = undefined
|
|
|
|
this.selectedAttrDoc = undefined
|
|
|
|
},
|
|
|
|
|
|
|
|
onInputTypeChange(structuredInput) {
|
|
|
|
this.structuredInput = structuredInput
|
|
|
|
this.response = undefined
|
|
|
|
this.error = undefined
|
2023-05-17 10:41:02 +02:00
|
|
|
this.$nextTick(() => {
|
|
|
|
if (structuredInput) {
|
|
|
|
this.$refs.actionName.focus()
|
|
|
|
} else {
|
|
|
|
this.$refs.rawAction.focus()
|
|
|
|
}
|
|
|
|
})
|
2021-02-20 23:12:54 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
onResponse(response) {
|
|
|
|
this.response = '<pre>' + JSON.stringify(response, null, 2) + '</pre>'
|
|
|
|
this.error = undefined
|
|
|
|
},
|
|
|
|
|
|
|
|
onError(error) {
|
|
|
|
this.response = undefined
|
|
|
|
this.error = error
|
|
|
|
},
|
|
|
|
|
|
|
|
onDone() {
|
|
|
|
this.running = false
|
|
|
|
},
|
|
|
|
|
|
|
|
executeAction() {
|
|
|
|
if (!this.action.name && !this.rawRequest || this.running)
|
|
|
|
return
|
|
|
|
|
|
|
|
this.running = true
|
|
|
|
if (this.structuredInput) {
|
|
|
|
const args = {
|
|
|
|
...Object.entries(this.action.args).reduce((args, param) => {
|
|
|
|
if (param[1].value != null) {
|
|
|
|
let value = param[1].value
|
|
|
|
try {
|
|
|
|
value = JSON.parse(value)
|
|
|
|
} catch (e) {
|
|
|
|
console.debug('Not a valid JSON value')
|
|
|
|
console.debug(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
args[param[0]] = value
|
|
|
|
}
|
|
|
|
return args
|
|
|
|
}, {}),
|
|
|
|
|
|
|
|
...this.action.extraArgs.reduce((args, param) => {
|
|
|
|
let value = args[param.value]
|
|
|
|
try {
|
|
|
|
value = JSON.parse(value)
|
|
|
|
} catch (e) {
|
|
|
|
console.debug('Not a valid JSON value')
|
|
|
|
console.debug(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
args[param.name] = value
|
|
|
|
return args
|
|
|
|
}, {})
|
|
|
|
}
|
|
|
|
|
|
|
|
this.request(this.action.name, args).then(this.onResponse).catch(this.onError).finally(this.onDone)
|
|
|
|
} else {
|
|
|
|
try {
|
2021-04-05 00:58:44 +02:00
|
|
|
const request = JSON.parse(this.rawRequest)
|
|
|
|
this.execute(request).then(this.onResponse).catch(this.onError).finally(this.onDone)
|
2021-02-20 23:12:54 +01:00
|
|
|
} catch (e) {
|
|
|
|
this.notify({
|
|
|
|
error: true,
|
|
|
|
title: 'Invalid JSON request',
|
|
|
|
text: e.toString(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
executeProcedure(event) {
|
|
|
|
if (!this.selectedProcedure.name || this.running)
|
|
|
|
return
|
|
|
|
|
|
|
|
event.stopPropagation()
|
|
|
|
this.running = true
|
|
|
|
const args = {
|
|
|
|
...Object.entries(this.selectedProcedure.args).reduce((args, param) => {
|
|
|
|
if (param[1] != null) {
|
|
|
|
let value = param[1]
|
|
|
|
try {
|
|
|
|
value = JSON.parse(value)
|
|
|
|
} catch (e) {
|
|
|
|
console.debug('Not a valid JSON value')
|
|
|
|
console.debug(value)
|
|
|
|
}
|
|
|
|
|
|
|
|
args[param[0]] = value
|
|
|
|
}
|
|
|
|
return args
|
|
|
|
}, {}),
|
|
|
|
}
|
|
|
|
|
|
|
|
this.request('procedure.' + this.selectedProcedure.name, args)
|
|
|
|
.then(this.onResponse).catch(this.onError).finally(this.onDone)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
mounted() {
|
2023-05-17 10:41:02 +02:00
|
|
|
this.$nextTick(() => {
|
|
|
|
this.$refs.actionName.focus()
|
|
|
|
})
|
|
|
|
|
2021-02-20 23:12:54 +01:00
|
|
|
this.refresh()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
@import "vars";
|
|
|
|
@import "~@/style/autocomplete.scss";
|
|
|
|
|
|
|
|
$params-desktop-width: 30em;
|
|
|
|
$params-tablet-width: 20em;
|
|
|
|
|
|
|
|
.execute-container {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
color: $default-fg-2;
|
|
|
|
font-weight: 400;
|
|
|
|
border-bottom: $default-border-2;
|
|
|
|
border-radius: 0 0 1em 1em;
|
|
|
|
|
|
|
|
form {
|
|
|
|
padding: 0;
|
|
|
|
margin: 0;
|
|
|
|
border-radius: 0;
|
|
|
|
border: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
.action-form {
|
2023-05-14 15:06:34 +02:00
|
|
|
background: $default-bg-2;
|
2021-02-20 23:12:54 +01:00
|
|
|
padding: 1em .5em;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title {
|
2023-05-17 10:41:02 +02:00
|
|
|
background: $header-bg;
|
2021-02-20 23:12:54 +01:00
|
|
|
padding: .5em;
|
|
|
|
border: $title-border;
|
|
|
|
box-shadow: $title-shadow;
|
|
|
|
font-size: 1.1em;
|
|
|
|
margin-bottom: 0 !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.request-type-container {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: row;
|
|
|
|
align-items: baseline;
|
|
|
|
|
|
|
|
label {
|
|
|
|
margin: 0 1em 0 .5em;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.request {
|
|
|
|
margin: 0 .5em;
|
|
|
|
|
|
|
|
form {
|
|
|
|
margin-bottom: 0 !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.autocomplete {
|
|
|
|
width: 80%;
|
|
|
|
max-width: 60em;
|
|
|
|
}
|
|
|
|
|
|
|
|
.action-name {
|
|
|
|
box-shadow: $action-name-shadow;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
[type=submit] {
|
|
|
|
margin-left: 2em;
|
|
|
|
}
|
|
|
|
|
|
|
|
.options {
|
|
|
|
display: flex;
|
|
|
|
margin-top: .5em;
|
|
|
|
margin-bottom: 1.5em;
|
|
|
|
padding-top: .5em;
|
|
|
|
|
|
|
|
@include until($tablet) {
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.params {
|
|
|
|
@include until($tablet) {
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
@include from($tablet) {
|
|
|
|
width: $params-tablet-width;
|
|
|
|
margin-right: 1.5em;
|
|
|
|
}
|
|
|
|
|
|
|
|
@include from($desktop) {
|
|
|
|
width: $params-desktop-width;
|
|
|
|
}
|
|
|
|
|
|
|
|
.param {
|
|
|
|
margin-bottom: .25em;
|
|
|
|
@include until($tablet) {
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.action-param-value {
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.add-param {
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
button {
|
|
|
|
width: 100%;
|
|
|
|
background: $extra-params-btn-bg;
|
|
|
|
border: $title-border;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.extra-param {
|
|
|
|
display: flex;
|
|
|
|
margin-bottom: .5em;
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
label {
|
|
|
|
margin-left: 0.25em;
|
|
|
|
}
|
|
|
|
|
|
|
|
.buttons {
|
|
|
|
display: flex;
|
|
|
|
flex-grow: 1;
|
|
|
|
justify-content: right;
|
|
|
|
}
|
|
|
|
|
2021-02-20 23:12:54 +01:00
|
|
|
.action-extra-param-del {
|
|
|
|
border: 0;
|
|
|
|
text-align: right;
|
|
|
|
padding: 0 .5em;
|
|
|
|
}
|
|
|
|
|
2023-05-14 15:06:34 +02:00
|
|
|
input[type=text] {
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
2021-02-20 23:12:54 +01:00
|
|
|
.buttons {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
margin-bottom: .25em;
|
|
|
|
|
|
|
|
button {
|
|
|
|
background: none;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
color: $default-hover-fg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.doc-container,
|
|
|
|
.output-container {
|
|
|
|
margin-top: .5em;
|
2021-02-20 23:26:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.output-container {
|
|
|
|
flex-grow: 1;
|
2021-02-20 23:12:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.attr-doc-container {
|
|
|
|
@include from($tablet) {
|
|
|
|
width: calc(100% - #{$params-tablet-width} - 2em);
|
|
|
|
}
|
|
|
|
|
|
|
|
@include from($desktop) {
|
|
|
|
width: calc(100% - #{$params-desktop-width} - 2em);
|
|
|
|
}
|
|
|
|
|
|
|
|
.doc {
|
|
|
|
width: 100%;
|
|
|
|
overflow: auto;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.widescreen {
|
|
|
|
@include until($tablet) {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
&.mobile {
|
|
|
|
width: 100%;
|
|
|
|
@include from($tablet) {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.doc-container,
|
|
|
|
.attr-doc-container {
|
|
|
|
.doc {
|
|
|
|
padding: 1em !important;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.output-container, .doc-container, .attr-doc-container {
|
|
|
|
max-height: 50vh;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
.title {
|
|
|
|
font-weight: normal;
|
|
|
|
font-size: 1em;
|
|
|
|
padding: .5em;
|
|
|
|
background: $section-title-bg;
|
|
|
|
border-radius: .5em;
|
|
|
|
|
|
|
|
.attr-name {
|
|
|
|
display: inline-block;
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.response,
|
|
|
|
.error,
|
|
|
|
.doc {
|
|
|
|
height: 100%;
|
|
|
|
padding: .5em .5em 0 .5em;
|
|
|
|
border-radius: 0 0 1em 1em;
|
|
|
|
overflow: auto;
|
|
|
|
}
|
|
|
|
|
|
|
|
.response {
|
|
|
|
background: $response-bg;
|
|
|
|
border: $response-border;
|
|
|
|
}
|
|
|
|
|
|
|
|
.error {
|
|
|
|
background: $error-bg;
|
|
|
|
border: $error-border;
|
|
|
|
}
|
|
|
|
|
|
|
|
.doc {
|
|
|
|
background: $doc-bg;
|
|
|
|
border: $doc-border;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
textarea {
|
|
|
|
width: 100%;
|
|
|
|
height: 10em;
|
|
|
|
margin-bottom: .5em;
|
|
|
|
padding: .5em;
|
|
|
|
border: $default-border-2;
|
|
|
|
border-radius: 1em;
|
|
|
|
box-shadow: $border-shadow-bottom-right;
|
|
|
|
outline: none;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
border: 1px solid $default-hover-fg-2;
|
|
|
|
}
|
|
|
|
|
|
|
|
&:focus {
|
|
|
|
border: 1px solid $selected-fg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.raw-request {
|
|
|
|
.first-row {
|
|
|
|
@include until($tablet) {
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
@include from($tablet) {
|
|
|
|
width: 80%;
|
|
|
|
max-width: 60em;
|
|
|
|
}
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
button {
|
|
|
|
margin-left: 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.procedures-container {
|
|
|
|
.procedure {
|
|
|
|
background: $background-color;
|
|
|
|
border-bottom: $default-border-2;
|
|
|
|
padding: 1.5em .5em;
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
background: $hover-bg;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.selected {
|
|
|
|
background: $selected-bg;
|
|
|
|
}
|
|
|
|
|
|
|
|
form {
|
|
|
|
background: none;
|
|
|
|
display: flex;
|
|
|
|
margin-bottom: 0 !important;
|
|
|
|
flex-direction: column;
|
|
|
|
box-shadow: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
.head {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.btn-container {
|
|
|
|
text-align: right;
|
|
|
|
}
|
|
|
|
|
|
|
|
button {
|
|
|
|
background: $procedure-submit-btn-bg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pre {
|
|
|
|
background: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
.run-btn {
|
2023-05-17 10:41:02 +02:00
|
|
|
background: $background-color;
|
2023-05-14 15:06:34 +02:00
|
|
|
border-radius: .25em;
|
|
|
|
padding: .5em 1.5em;
|
|
|
|
box-shadow: $primary-btn-shadow;
|
2023-05-17 10:41:02 +02:00
|
|
|
cursor: pointer;
|
2021-02-20 23:12:54 +01:00
|
|
|
|
|
|
|
&:hover {
|
2023-05-14 15:06:34 +02:00
|
|
|
background: $hover-bg;
|
|
|
|
box-shadow: none;
|
2021-02-20 23:12:54 +01:00
|
|
|
}
|
2023-05-17 10:41:02 +02:00
|
|
|
|
|
|
|
&:disabled {
|
|
|
|
opacity: 0.7;
|
|
|
|
color: $default-fg-2;
|
|
|
|
cursor: initial;
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
background: $background-color;
|
|
|
|
box-shadow: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
&:not(disabled) {
|
|
|
|
}
|
2021-02-20 23:12:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|