frequi_origin/src/components/charts/PlotConfigurator.vue

375 lines
9.7 KiB
Vue
Raw Normal View History

<template>
2020-07-01 18:22:29 +00:00
<div v-if="columns">
2021-06-23 04:45:18 +00:00
<div v-if="true" class="col-mb-3 ml-2">
2020-08-01 18:43:14 +00:00
<b-form-radio-group
v-model="plotOption"
2020-08-08 13:57:36 +00:00
class="w-100"
2020-08-01 18:43:14 +00:00
:options="plotOptions"
buttons
button-variant="outline-primary"
>
</b-form-radio-group>
</div>
2020-08-08 13:57:36 +00:00
<div v-if="plotOption == 'subplots'" class="col-mb-3">
2020-08-01 18:43:14 +00:00
<hr />
<b-form-group label="Subplot" label-for="FieldSel">
2020-08-08 13:57:36 +00:00
<b-form-select id="FieldSel" v-model="selSubPlot" :options="subplots" :select-size="4">
2020-07-01 18:22:29 +00:00
</b-form-select>
</b-form-group>
</div>
<b-form-group v-if="plotOption == 'subplots'" label="New subplot" label-for="newSubplot">
2020-08-01 18:43:14 +00:00
<b-input-group size="sm">
2020-08-08 13:57:36 +00:00
<b-form-input id="newSubplot" v-model="newSubplotName" class="addPlot"></b-form-input>
2020-07-01 18:39:03 +00:00
<b-input-group-append>
<b-button @click="addSubplot">+</b-button>
2020-08-08 13:57:36 +00:00
<b-button v-if="selSubPlot" @click="delSubplot">-</b-button>
2020-07-01 18:39:03 +00:00
</b-input-group-append>
</b-input-group>
2020-07-01 18:22:29 +00:00
</b-form-group>
2020-07-01 18:39:03 +00:00
<hr />
2020-08-09 08:50:02 +00:00
<div class="row">
<b-form-group class="col" label="Add indicator" label-for="indicatorSelector">
<b-form-select
id="indicatorSelector"
v-model="selAvailableIndicator"
:options="columns"
:select-size="4"
>
</b-form-select>
</b-form-group>
<div class="col-1 px-0 text-center">
<b-button
class="mt-5"
variant="primary"
title="Add indicator to plot"
size="sm"
:disabled="!selAvailableIndicator"
@click="addIndicator"
>
&gt;
</b-button>
<b-button
variant="primary"
title="Remove indicator to plot"
size="sm"
:disabled="!selIndicator"
@click="removeIndicator"
>
&lt;
</b-button>
</div>
<b-form-group class="col" label="Used indicators" label-for="selectedIndicators">
<b-form-select
id="selectedIndicators"
v-model="selIndicator"
:options="usedColumns"
:select-size="4"
>
</b-form-select>
</b-form-group>
</div>
2021-06-23 04:45:18 +00:00
<b-form-group label="Type" label-for="plotTypeSelector">
<b-form-select
id="plotTypeSelector"
v-model="graphType"
size="sm"
:options="availableGraphTypes"
>
2020-07-01 18:59:45 +00:00
</b-form-select>
</b-form-group>
2020-07-01 18:39:03 +00:00
<hr />
2020-07-01 18:22:29 +00:00
2020-08-01 18:43:14 +00:00
<b-form-group label="Color" label-for="colsel" size="sm">
2020-07-01 18:39:03 +00:00
<b-input-group>
<b-input-group-prepend>
2020-08-08 13:57:36 +00:00
<div :style="{ 'background-color': selColor }" class="colorbox mr-2"></div>
2020-07-01 18:39:03 +00:00
</b-input-group-prepend>
2020-08-01 18:43:14 +00:00
<b-form-input id="colsel" v-model="selColor" size="sm"> </b-form-input>
2020-07-01 18:39:03 +00:00
<b-input-group-append>
2020-08-08 13:57:36 +00:00
<b-button variant="primary" size="sm" @click="newColor">&#x21bb;</b-button>
2020-07-01 18:39:03 +00:00
</b-input-group-append>
</b-input-group>
2020-07-01 18:22:29 +00:00
</b-form-group>
2020-07-01 18:39:03 +00:00
<hr />
2020-08-24 18:05:07 +00:00
<b-form-group label="Plot config name" label-for="idPlotConfigName">
2021-06-23 04:45:18 +00:00
<b-form-input
id="idPlotConfigName"
v-model="plotConfigName"
size="sm"
:options="availableGraphTypes"
>
2020-08-24 18:05:07 +00:00
</b-form-input>
</b-form-group>
2021-06-22 19:08:03 +00:00
<div class="row px-2">
<b-button class="ml-1" variant="primary" size="sm" @click="loadPlotConfig">Load</b-button>
2020-08-08 13:57:36 +00:00
<b-button class="ml-1" variant="primary" size="sm" @click="loadPlotConfigFromStrategy">
Load from strategy
</b-button>
<b-button
2020-08-01 18:43:14 +00:00
class="ml-1"
variant="primary"
size="sm"
data-toggle="tooltip"
title="Save configuration"
2020-08-08 13:57:36 +00:00
@click="savePlotConfig"
>Save</b-button
>
<b-button
id="showButton"
2020-08-08 13:57:36 +00:00
class="ml-1"
variant="primary"
size="sm"
title="Show configuration for easy transfer to a strategy"
2020-08-08 13:57:36 +00:00
@click="showConfig = !showConfig"
>Show</b-button
>
2021-06-22 19:08:03 +00:00
<b-button
v-if="showConfig"
class="ml-1"
variant="primary"
size="sm"
title="Load configuration from text box below"
@click="resetConfig"
>Reset</b-button
>
<b-button
2020-08-08 13:57:36 +00:00
v-if="showConfig"
2020-08-01 18:43:14 +00:00
class="ml-1"
variant="primary"
size="sm"
title="Load configuration from text box below"
2020-08-08 13:57:36 +00:00
@click="loadConfigFromString"
>Load from String</b-button
>
</div>
2021-06-22 19:08:03 +00:00
<div v-if="showConfig" class="col-mb-5 ml-1 mt-2">
<b-textarea
id="TextArea"
v-model="plotConfigJson"
2020-08-08 13:57:36 +00:00
class="textArea"
size="sm"
:state="tempPlotConfigValid"
>
</b-textarea>
2020-07-01 18:22:29 +00:00
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Emit } from 'vue-property-decorator';
import { namespace } from 'vuex-class';
2020-08-08 13:57:36 +00:00
import { PlotConfig, EMPTY_PLOTCONFIG } from '@/types';
2020-07-24 05:57:14 +00:00
import randomColor from '@/shared/randomColor';
2020-08-08 13:57:36 +00:00
import { getCustomPlotConfig } from '@/shared/storage';
const ftbot = namespace('ftbot');
@Component({})
export default class PlotConfigurator extends Vue {
@Prop({ required: true }) value!: PlotConfig;
@Prop({ required: true }) columns!: Array<string>;
2021-06-23 04:45:18 +00:00
@Prop({ required: true }) asModal!: boolean;
@Emit('input')
emitPlotConfig() {
return this.plotConfig;
}
2020-08-07 04:57:05 +00:00
@ftbot.Action getStrategyPlotConfig;
@ftbot.State strategyPlotConfig;
plotConfig: PlotConfig = EMPTY_PLOTCONFIG;
2020-08-01 18:43:14 +00:00
plotOptions = [
{ text: 'Main Plot', value: 'main_plot' },
{ text: 'Subplots', value: 'subplots' },
];
plotOption = 'main_plot';
2020-08-24 18:05:07 +00:00
plotConfigName = 'default';
newSubplotName = '';
2020-08-01 18:43:14 +00:00
selAvailableIndicator = '';
selIndicator = '';
2020-07-01 18:59:45 +00:00
graphType = 'line';
availableGraphTypes = ['line', 'bar', 'scatter'];
showConfig = false;
2020-08-01 18:43:14 +00:00
selSubPlot = '';
tempPlotConfig?: PlotConfig = undefined;
tempPlotConfigValid = true;
selColor = randomColor();
2020-08-24 18:05:07 +00:00
@ftbot.Mutation saveCustomPlotConfig;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2020-08-24 18:05:07 +00:00
@ftbot.Mutation updatePlotConfigName!: (plotConfigName: string) => void;
2020-08-08 13:25:58 +00:00
@ftbot.State('plotConfigName') usedPlotConfigName!: string;
get plotConfigJson() {
return JSON.stringify(this.plotConfig, null, 2);
}
set plotConfigJson(newValue: string) {
try {
this.tempPlotConfig = JSON.parse(newValue);
// TODO: Should Validate schema validity (should be PlotConfig type...)
this.tempPlotConfigValid = true;
} catch (err) {
this.tempPlotConfigValid = false;
}
}
2021-06-23 04:45:18 +00:00
get subplots(): string[] {
// Subplot keys (for selection window)
2021-06-23 04:45:18 +00:00
return ['main_plot', ...Object.keys(this.plotConfig.subplots)];
}
2021-06-23 04:45:18 +00:00
get usedColumns(): string[] {
2020-08-01 18:43:14 +00:00
if (this.isMainPlot) {
return Object.keys(this.plotConfig.main_plot);
}
if (this.selSubPlot in this.plotConfig[this.plotOption]) {
return Object.keys(this.plotConfig[this.plotOption][this.selSubPlot]);
}
return [];
}
get isMainPlot() {
return this.plotOption === 'main_plot';
}
mounted() {
this.plotConfig = this.value;
2020-08-08 13:25:58 +00:00
this.plotConfigName = this.usedPlotConfigName;
}
2020-07-01 18:22:29 +00:00
newColor() {
this.selColor = randomColor();
}
2020-08-01 18:43:14 +00:00
addIndicator() {
console.log(this.plotConfig);
const { plotConfig } = this;
2020-08-01 18:43:14 +00:00
if (this.isMainPlot) {
console.log(`Adding ${this.selAvailableIndicator} to MainPlot`);
plotConfig[this.plotOption][this.selAvailableIndicator] = {
color: this.selColor,
type: this.graphType,
};
} else {
2020-08-01 18:43:14 +00:00
console.log(`Adding ${this.selAvailableIndicator} to ${this.selSubPlot}`);
plotConfig[this.plotOption][this.selSubPlot][this.selAvailableIndicator] = {
2020-07-01 18:59:45 +00:00
color: this.selColor,
type: this.graphType,
};
}
this.plotConfig = { ...plotConfig };
2020-08-01 18:43:14 +00:00
this.selAvailableIndicator = '';
// Reset random color
2020-07-01 18:22:29 +00:00
this.newColor();
2020-08-01 18:43:14 +00:00
this.emitPlotConfig();
}
removeIndicator() {
console.log(this.plotConfig);
2020-08-01 18:43:14 +00:00
const { plotConfig } = this;
if (this.isMainPlot) {
console.log(`Removing ${this.selIndicator} from MainPlot`);
delete plotConfig[this.plotOption][this.selIndicator];
} else {
console.log(`Removing ${this.selIndicator} from ${this.selSubPlot}`);
delete plotConfig[this.plotOption][this.selSubPlot][this.selIndicator];
}
this.plotConfig = { ...plotConfig };
console.log(this.plotConfig);
this.selIndicator = '';
this.emitPlotConfig();
}
addSubplot() {
this.plotConfig.subplots = {
...this.plotConfig.subplots,
[this.newSubplotName]: {},
};
2020-08-01 18:43:14 +00:00
this.selSubPlot = this.newSubplotName;
this.newSubplotName = '';
console.log(this.plotConfig);
this.emitPlotConfig();
}
2020-07-01 18:22:29 +00:00
delSubplot() {
2020-08-01 18:43:14 +00:00
delete this.plotConfig.subplots[this.selSubPlot];
2020-07-01 18:22:29 +00:00
this.plotConfig.subplots = { ...this.plotConfig.subplots };
}
savePlotConfig() {
2020-08-24 18:05:07 +00:00
this.saveCustomPlotConfig({ [this.plotConfigName]: this.plotConfig });
}
loadPlotConfig() {
2020-08-08 13:57:36 +00:00
this.plotConfig = getCustomPlotConfig(this.plotConfigName);
console.log(this.plotConfig);
console.log('loading config');
this.emitPlotConfig();
}
loadConfigFromString() {
// this.plotConfig = JSON.parse();
if (this.tempPlotConfig !== undefined && this.tempPlotConfigValid) {
this.plotConfig = this.tempPlotConfig;
this.emitPlotConfig();
}
}
2021-06-22 19:08:03 +00:00
resetConfig() {
this.plotConfig = { ...EMPTY_PLOTCONFIG };
}
async loadPlotConfigFromStrategy() {
2020-08-07 04:57:05 +00:00
await this.getStrategyPlotConfig();
this.plotConfig = this.strategyPlotConfig;
this.emitPlotConfig();
}
}
</script>
2020-07-01 18:22:29 +00:00
<style scoped>
.textArea {
min-height: 250px;
}
.colorbox {
2020-07-01 18:39:03 +00:00
border-radius: 50%;
2020-08-01 18:43:14 +00:00
margin-top: auto;
margin-bottom: auto;
2020-07-01 18:22:29 +00:00
height: 25px;
width: 25px;
2020-07-01 18:39:03 +00:00
vertical-align: center;
2020-07-01 18:22:29 +00:00
}
2020-08-01 18:43:14 +00:00
.form-group {
margin-bottom: 0.5rem;
}
hr {
margin-bottom: 0.5rem;
margin-top: 0.5rem;
}
</style>