composition: plotconfig

This commit is contained in:
Matthias 2022-04-17 09:57:39 +02:00
parent 2a49381c6c
commit 5298127402

View File

@ -120,234 +120,242 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop, Emit, Watch } from 'vue-property-decorator';
import { namespace } from 'vuex-class';
import { PlotConfig, EMPTY_PLOTCONFIG, IndicatorConfig } from '@/types'; import { PlotConfig, EMPTY_PLOTCONFIG, IndicatorConfig } from '@/types';
import { getCustomPlotConfig } from '@/shared/storage'; import { getCustomPlotConfig } from '@/shared/storage';
import PlotIndicator from '@/components/charts/PlotIndicator.vue'; import PlotIndicator from '@/components/charts/PlotIndicator.vue';
import { BotStoreGetters } from '@/store/modules/ftbot';
import StoreModules from '@/store/storeSubModules'; import StoreModules from '@/store/storeSubModules';
import { showAlert } from '@/stores/alerts'; import { showAlert } from '@/stores/alerts';
const ftbot = namespace(StoreModules.ftbot); import { defineComponent, computed, ref, watch, onMounted } from '@vue/composition-api';
import { useNamespacedActions, useNamespacedGetters } from 'vuex-composition-helpers';
@Component({ export default defineComponent({
name: 'PlotConfigurator',
components: { PlotIndicator }, components: { PlotIndicator },
}) props: {
export default class PlotConfigurator extends Vue { value: { type: Object as () => PlotConfig, required: true },
@Prop({ required: true }) value!: PlotConfig; columns: { required: true, type: Array as () => string[] },
asModal: { required: false, default: true, type: Boolean },
},
emits: ['input'],
setup(props, { emit }) {
const { getStrategyPlotConfig, saveCustomPlotConfig, updatePlotConfigName } =
useNamespacedActions(StoreModules.ftbot, [
'getStrategyPlotConfig',
'saveCustomPlotConfig',
'updatePlotConfigName',
]);
const { strategyPlotConfig, plotConfigName } = useNamespacedGetters(StoreModules.ftbot, [
'strategyPlotConfig',
'plotConfigName',
]);
const plotConfig = ref<PlotConfig>(EMPTY_PLOTCONFIG);
@Prop({ required: true }) columns!: Array<string>; const plotOptions = [
{ text: 'Main Plot', value: 'main_plot' },
{ text: 'Subplots', value: 'subplots' },
];
const plotConfigNameLoc = ref('default');
const newSubplotName = ref('');
const selAvailableIndicator = ref('');
const selIndicatorName = ref('');
const addNewIndicator = ref(false);
const showConfig = ref(false);
const selSubPlot = ref('main_plot');
const tempPlotConfig = ref<PlotConfig>();
const tempPlotConfigValid = ref(true);
@Prop({ required: false, default: true }) asModal!: boolean; const isMainPlot = computed(() => {
return selSubPlot.value === 'main_plot';
});
@Emit('input') const currentPlotConfig = computed(() => {
emitPlotConfig() { if (isMainPlot.value) {
return this.plotConfig; return plotConfig.value.main_plot;
} }
@ftbot.Action getStrategyPlotConfig; return plotConfig.value.subplots[selSubPlot.value];
});
const subplots = computed((): string[] => {
// Subplot keys (for selection window)
return ['main_plot', ...Object.keys(plotConfig.value.subplots)];
});
const usedColumns = computed((): string[] => {
if (isMainPlot.value) {
return Object.keys(plotConfig.value.main_plot);
}
if (selSubPlot.value in plotConfig.value.subplots) {
return Object.keys(plotConfig.value.subplots[selSubPlot.value]);
}
return [];
});
@ftbot.Getter [BotStoreGetters.strategyPlotConfig]; const addIndicator = (newIndicator: Record<string, IndicatorConfig>) => {
console.log(plotConfig.value);
get selIndicator(): Record<string, IndicatorConfig> { // const { plotConfig.value } = this;
if (this.addNewIndicator) { const name = Object.keys(newIndicator)[0];
return {}; const indicator = newIndicator[name];
} if (isMainPlot.value) {
if (this.selIndicatorName) { console.log(`Adding ${name} to MainPlot`);
return { plotConfig.value.main_plot[name] = { ...indicator };
[this.selIndicatorName]: this.currentPlotConfig[this.selIndicatorName], } else {
}; console.log(`Adding ${name} to ${selSubPlot.value}`);
} plotConfig.value.subplots[selSubPlot.value][name] = { ...indicator };
return {}; }
}
set selIndicator(newValue: Record<string, IndicatorConfig>) { plotConfig.value = { ...plotConfig.value };
// console.log('newValue', newValue); // Reset random color
const name = Object.keys(newValue)[0]; addNewIndicator.value = false;
// this.currentPlotConfig[this.selIndicatorName] = { ...newValue[name] }; emit('input', plotConfig.value);
// this.emitPlotConfig();
if (name && newValue) {
this.addIndicator(newValue);
} else {
this.addNewIndicator = false;
}
}
plotConfig: PlotConfig = EMPTY_PLOTCONFIG;
plotOptions = [
{ text: 'Main Plot', value: 'main_plot' },
{ text: 'Subplots', value: 'subplots' },
];
plotConfigNameLoc = 'default';
newSubplotName = '';
selAvailableIndicator = '';
selIndicatorName = '';
addNewIndicator = false;
showConfig = false;
selSubPlot = 'main_plot';
tempPlotConfig?: PlotConfig = undefined;
tempPlotConfigValid = true;
@ftbot.Action saveCustomPlotConfig;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@ftbot.Action updatePlotConfigName!: (plotConfigName: string) => void;
@ftbot.Getter [BotStoreGetters.plotConfigName]!: 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;
}
}
get subplots(): string[] {
// Subplot keys (for selection window)
return ['main_plot', ...Object.keys(this.plotConfig.subplots)];
}
get usedColumns(): string[] {
if (this.isMainPlot) {
return Object.keys(this.plotConfig.main_plot);
}
if (this.selSubPlot in this.plotConfig.subplots) {
return Object.keys(this.plotConfig.subplots[this.selSubPlot]);
}
return [];
}
get isMainPlot() {
return this.selSubPlot === 'main_plot';
}
get currentPlotConfig() {
if (this.isMainPlot) {
return this.plotConfig.main_plot;
}
return this.plotConfig.subplots[this.selSubPlot];
}
mounted() {
console.log('Config Mounted', this.value);
this.plotConfig = this.value;
this.plotConfigNameLoc = this.plotConfigName;
}
@Watch('value')
watchValue() {
this.plotConfig = this.value;
this.plotConfigNameLoc = this.plotConfigName;
}
addIndicator(newIndicator: Record<string, IndicatorConfig>) {
console.log(this.plotConfig);
const { plotConfig } = this;
const name = Object.keys(newIndicator)[0];
const indicator = newIndicator[name];
if (this.isMainPlot) {
console.log(`Adding ${name} to MainPlot`);
plotConfig.main_plot[name] = { ...indicator };
} else {
console.log(`Adding ${name} to ${this.selSubPlot}`);
plotConfig.subplots[this.selSubPlot][name] = { ...indicator };
}
this.plotConfig = { ...plotConfig };
// Reset random color
this.addNewIndicator = false;
this.emitPlotConfig();
}
removeIndicator() {
console.log(this.plotConfig);
const { plotConfig } = this;
if (this.isMainPlot) {
console.log(`Removing ${this.selIndicatorName} from MainPlot`);
delete plotConfig.main_plot[this.selIndicatorName];
} else {
console.log(`Removing ${this.selIndicatorName} from ${this.selSubPlot}`);
delete plotConfig.subplots[this.selSubPlot][this.selIndicatorName];
}
this.plotConfig = { ...plotConfig };
console.log(this.plotConfig);
this.selIndicatorName = '';
this.emitPlotConfig();
}
addSubplot() {
this.plotConfig.subplots = {
...this.plotConfig.subplots,
[this.newSubplotName]: {},
}; };
this.selSubPlot = this.newSubplotName;
this.newSubplotName = '';
console.log(this.plotConfig); const selIndicator = computed({
this.emitPlotConfig(); get() {
} if (addNewIndicator.value) {
return {};
}
if (selIndicatorName.value) {
return {
[selIndicatorName.value]: currentPlotConfig.value[selIndicatorName.value],
};
}
return {};
},
set(newValue: Record<string, IndicatorConfig>) {
// console.log('newValue', newValue);
const name = Object.keys(newValue)[0];
// this.currentPlotConfig[this.selIndicatorName] = { ...newValue[name] };
// this.emitPlotConfig();
if (name && newValue) {
addIndicator(newValue);
} else {
addNewIndicator.value = false;
}
},
});
delSubplot() { const plotConfigJson = computed({
delete this.plotConfig.subplots[this.selSubPlot]; get() {
this.plotConfig.subplots = { ...this.plotConfig.subplots }; return JSON.stringify(plotConfig.value, null, 2);
this.selSubPlot = ''; },
} set(newValue: string) {
try {
tempPlotConfig.value = JSON.parse(newValue);
// TODO: Should Validate schema validity (should be PlotConfig type...)
tempPlotConfigValid.value = true;
} catch (err) {
tempPlotConfigValid.value = false;
}
},
});
savePlotConfig() { const removeIndicator = () => {
this.saveCustomPlotConfig({ [this.plotConfigNameLoc]: this.plotConfig }); console.log(plotConfig.value);
} // const { plotConfig } = this;
if (isMainPlot.value) {
console.log(`Removing ${selIndicatorName.value} from MainPlot`);
delete plotConfig.value.main_plot[selIndicatorName.value];
} else {
console.log(`Removing ${selIndicatorName.value} from ${selSubPlot.value}`);
delete plotConfig.value.subplots[selSubPlot.value][selIndicatorName.value];
}
loadPlotConfig() { plotConfig.value = { ...plotConfig.value };
this.plotConfig = getCustomPlotConfig(this.plotConfigNameLoc); console.log(plotConfig.value);
console.log(this.plotConfig); selIndicatorName.value = '';
console.log('loading config'); emit('input', plotConfig.value);
this.emitPlotConfig(); };
} const addSubplot = () => {
plotConfig.value.subplots = {
...plotConfig.value.subplots,
[newSubplotName.value]: {},
};
selSubPlot.value = newSubplotName.value;
newSubplotName.value = '';
loadConfigFromString() { console.log(plotConfig.value);
// this.plotConfig = JSON.parse(); emit('input', plotConfig.value);
if (this.tempPlotConfig !== undefined && this.tempPlotConfigValid) { };
this.plotConfig = this.tempPlotConfig;
this.emitPlotConfig();
}
}
resetConfig() { const delSubplot = () => {
this.plotConfig = { ...EMPTY_PLOTCONFIG }; delete plotConfig.value.subplots[selSubPlot.value];
} plotConfig.value.subplots = { ...plotConfig.value.subplots };
selSubPlot.value = '';
};
const loadPlotConfig = () => {
plotConfig.value = getCustomPlotConfig(plotConfigNameLoc.value);
console.log(plotConfig.value);
console.log('loading config');
emit('input', plotConfig.value);
};
async loadPlotConfigFromStrategy() { const loadConfigFromString = () => {
try { // this.plotConfig = JSON.parse();
await this.getStrategyPlotConfig(); if (tempPlotConfig.value !== undefined && tempPlotConfigValid.value) {
this.plotConfig = this.strategyPlotConfig; plotConfig.value = tempPlotConfig.value;
this.emitPlotConfig(); emit('input', plotConfig.value);
} catch (data) { }
// };
showAlert('Failed to load Plot configuration from Strategy.'); const resetConfig = () => {
} plotConfig.value = { ...EMPTY_PLOTCONFIG };
} };
} const loadPlotConfigFromStrategy = async () => {
try {
await getStrategyPlotConfig();
plotConfig.value = strategyPlotConfig.value;
emit('input', plotConfig.value);
} catch (data) {
//
showAlert('Failed to load Plot configuration from Strategy.');
}
};
const savePlotConfig = () => {
saveCustomPlotConfig({ [plotConfigNameLoc.value]: plotConfig.value });
};
watch(props.value, () => {
console.log('config value');
plotConfig.value = props.value;
plotConfigNameLoc.value = plotConfigName.value;
});
onMounted(() => {
console.log('Config Mounted', props.value);
plotConfig.value = props.value;
plotConfigNameLoc.value = plotConfigName.value;
});
return {
saveCustomPlotConfig,
getStrategyPlotConfig,
updatePlotConfigName,
strategyPlotConfig,
plotConfigName,
addIndicator,
removeIndicator,
addSubplot,
delSubplot,
loadPlotConfig,
loadConfigFromString,
resetConfig,
loadPlotConfigFromStrategy,
savePlotConfig,
showConfig,
addNewIndicator,
selIndicatorName,
usedColumns,
selSubPlot,
newSubplotName,
subplots,
plotConfigNameLoc,
selIndicator,
plotConfigJson,
tempPlotConfigValid,
};
},
});
</script> </script>
<style scoped> <style scoped>
@ -358,6 +366,7 @@ export default class PlotConfigurator extends Vue {
.form-group { .form-group {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
hr { hr {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
margin-top: 0.5rem; margin-top: 0.5rem;