Resolve "WIP: UTXO Selection and Storage"
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<div class="input-wrapper">
|
||||
<h2>Input</h2>
|
||||
|
||||
<div class="form-group-row" :class="{ 'extended': state.selectedFromFunction?.extendedInput }">
|
||||
<div class="form-group select-group">
|
||||
<label for="functionSelect">Select Function</label>
|
||||
<select v-model="state.selectedFromFunction">
|
||||
<option v-for="fromFunction of props.fromFunctions" :key="fromFunction.label" :value="fromFunction">{{ fromFunction.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group input-group" :class="{ 'extended': state.selectedFromFunction?.extendedInput }">
|
||||
<template v-for="(_input, i) of state.selectedFromFunction.inputs" :key="i">
|
||||
<label for="field">{{ state.selectedFromFunction.inputs[i] }}</label>
|
||||
<div>
|
||||
<textarea
|
||||
v-if="state.selectedFromFunction?.extendedInput"
|
||||
v-model="state.selectedFromFunction.models[i]"
|
||||
class="extended-input"
|
||||
@input="autoGrow($event.target)"
|
||||
></textarea>
|
||||
<input
|
||||
v-else
|
||||
type="text"
|
||||
v-model="state.selectedFromFunction.models[i]"
|
||||
/>
|
||||
<div v-if="state.error" class="text-error">{{ state.error }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="gradient-button" @click="() => setPrimitive(() => state.selectedFromFunction.callback(state.selectedFromFunction.models))">Create Output</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section output-section">
|
||||
<h2>Output</h2>
|
||||
|
||||
<template v-for="(toFunction, i) of toFunctions" :key="i">
|
||||
<div>
|
||||
<div class="output-box-container">
|
||||
<LabelledSection :label="toFunction.label" :content="getPrimitive(() => toFunction.callback(state.primitive))" />
|
||||
<CopyButton :content="getPrimitive(() => toFunction.callback(state.primitive))" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="state.methods.length && state.primitive">
|
||||
<h2>Methods</h2>
|
||||
|
||||
<div class="form-group-row" :class="{ 'extended': state.selectedMethod?.extendedInput }">
|
||||
<div class="form-group select-group">
|
||||
<label for="functionSelect">Select Function</label>
|
||||
<select v-model="state.selectedMethod">
|
||||
<option v-for="method of props.methods" :key="method.label" :value="method">{{ method.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group input-group" :class="{ 'extended': state.selectedMethod?.extendedInput }">
|
||||
<template v-for="(_input, i) of state.selectedMethod.inputs" :key="i">
|
||||
<label for="field">{{ state.selectedMethod.inputs[i] }}</label>
|
||||
<div>
|
||||
<textarea
|
||||
v-if="state.selectedMethod?.extendedInput"
|
||||
v-model="state.selectedMethod.models[i]"
|
||||
class="extended-input"
|
||||
@input="autoGrow($event.target)"
|
||||
></textarea>
|
||||
<input
|
||||
v-else
|
||||
type="text"
|
||||
v-model="state.selectedMethod.models[i]"
|
||||
/>
|
||||
<div v-if="state.error" class="text-error">{{ state.error }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="gradient-button" @click="() => executeMethod(state.selectedMethod.callback(state.primitive, state.selectedMethod.models))">Execute Method</button>
|
||||
</div>
|
||||
<!-- Result -->
|
||||
<div>
|
||||
<div class="output-box-container">
|
||||
<LabelledSection label="Result" :content="state.selectedMethod.result" />
|
||||
<CopyButton :content="state.selectedMethod.result" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup generic="Primitive" lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import LabelledSection from './LabelledSection.vue';
|
||||
import CopyButton from './CopyButton.vue';
|
||||
|
||||
export interface FromFunction<Primitive> {
|
||||
// The label of the function
|
||||
label: string,
|
||||
|
||||
// Array of inputs that the function takes
|
||||
inputs: Array<string>,
|
||||
|
||||
// Array of models that the input stores its value in
|
||||
models: Array<any>,
|
||||
|
||||
// Function that takes the models and returns the primitive
|
||||
callback: (value: Array<any>) => Primitive,
|
||||
|
||||
// Whether the input is extended onto a new line
|
||||
extendedInput?: boolean
|
||||
}
|
||||
|
||||
export interface ToFunction<Primitive> {
|
||||
label: string;
|
||||
callback: (primitive: Primitive) => string;
|
||||
result?: string;
|
||||
}
|
||||
|
||||
export interface Method<Primitive> {
|
||||
// The label of the function
|
||||
label: string;
|
||||
|
||||
// Array of inputs that the function takes
|
||||
inputs: Array<string>,
|
||||
|
||||
// Array of models that the input stores its value in
|
||||
models: Array<any>,
|
||||
|
||||
// Result of method execution,
|
||||
result?: string;
|
||||
|
||||
// Function that takes the models and returns the primitive
|
||||
callback: (primitive: Primitive, value: Array<any>) => string;
|
||||
|
||||
// Whether the input is extended onto a new line
|
||||
extendedInput?: boolean
|
||||
}
|
||||
|
||||
export interface Props<Primitive> {
|
||||
fromFunctions: Array<FromFunction<Primitive>>,
|
||||
toFunctions: Array<ToFunction<Primitive>>,
|
||||
methods?: Array<Method<Primitive>>,
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props<Primitive>>(), {
|
||||
fromFunctions: () => [],
|
||||
toFunctions: () => [],
|
||||
methods: () => [],
|
||||
});
|
||||
|
||||
const state: Ref<{
|
||||
fromFunctions: Array<FromFunction<Primitive>>,
|
||||
toFunctions: Array<ToFunction<Primitive>>,
|
||||
methods: Array<Method<Primitive>>,
|
||||
|
||||
// Selected In Function
|
||||
selectedFromFunction: FromFunction<Primitive>,
|
||||
|
||||
// Selected Method
|
||||
selectedMethod?: Method<Primitive>,
|
||||
|
||||
// The Primitive.
|
||||
primitive?: Primitive,
|
||||
|
||||
// Error to display if an invalid input was given.
|
||||
error?: string;
|
||||
}> = ref({
|
||||
// From functions, to functions and methods.
|
||||
fromFunctions: [ ...props.fromFunctions ],
|
||||
toFunctions: [ ...props.toFunctions ],
|
||||
methods: [ ...props.methods ],
|
||||
|
||||
// The selected function.
|
||||
selectedFromFunction: props.fromFunctions[0],
|
||||
|
||||
// The selected method.
|
||||
selectedMethod: props.methods[0] || undefined,
|
||||
|
||||
// The Primitive.
|
||||
primitive: undefined,
|
||||
})
|
||||
|
||||
async function setPrimitive(functionToExecute: () => Primitive | Promise<Primitive>): void {
|
||||
try {
|
||||
state.value.primitive = await functionToExecute();
|
||||
state.value.error = undefined;
|
||||
|
||||
state.value.toFunctions.forEach((wrappedMethod, i) => {
|
||||
state.value.toFunctions[i].result = wrappedMethod.callback(state.value.primitive)
|
||||
});
|
||||
} catch(error: any) {
|
||||
state.value.error = `${error}`;
|
||||
}
|
||||
}
|
||||
|
||||
function getPrimitive(functionToExecute: () => string): string {
|
||||
try {
|
||||
if(!state.value.primitive) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return functionToExecute();
|
||||
} catch(error: any) {
|
||||
return error.message;
|
||||
}
|
||||
}
|
||||
|
||||
async function executeMethod(wrappedMethod: () => string | Promise<string>): string {
|
||||
try {
|
||||
if(!state.value.primitive) {
|
||||
return '';
|
||||
}
|
||||
|
||||
state.value.selectedMethod.result = await wrappedMethod;
|
||||
} catch(error: any) {
|
||||
return error.message;
|
||||
}
|
||||
};
|
||||
|
||||
// Select the first "from" function.
|
||||
state.value.selectedFromFunction = state.value.fromFunctions[0];
|
||||
|
||||
const autoGrow = (element: HTMLTextAreaElement) => {
|
||||
element.style.height = 'auto'
|
||||
element.style.height = `${Math.min(element.scrollHeight, 300)}px`
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.text-error {
|
||||
color: #f46666;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user