Merge branch 'main' into pr/Tako88/1265

This commit is contained in:
Matthias 2023-06-04 08:36:35 +02:00
commit af05f9fc88
11 changed files with 129 additions and 51 deletions

View File

@ -1,18 +1,22 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="/favicon.ico">
<title>FreqUI</title>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="/favicon.ico">
<title>FreqUI</title>
</head>
<body data-bs-theme="dark">
<noscript>
<strong>We're sorry but FreqUI doesn't work properly without JavaScript enabled. Please enable it to
continue.</strong>
</noscript>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</head>
<body>
<noscript>
<strong>We're sorry but FreqUI doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@ -6,8 +6,11 @@
<script setup lang="ts">
import { useSettingsStore } from '@/stores/settings';
import { useColorMode } from 'bootstrap-vue-next';
import { onMounted, ref } from 'vue';
const mode = useColorMode();
const activeTheme = ref('');
const settingsStore = useSettingsStore();
@ -18,17 +21,14 @@ const setTheme = (themeName: string) => {
}
if (themeName.toLowerCase() === 'bootstrap' || themeName.toLowerCase() === 'bootstrap_dark') {
// const styles = document.getElementsByTagName('style');
document.documentElement.setAttribute(
'data-theme',
themeName.toLowerCase() === 'bootstrap' ? 'light' : 'dark',
);
if (activeTheme.value) {
// Only transition if simple mode is active
document.documentElement.classList.add('ft-theme-transition');
document.body.classList.add('ft-theme-transition');
window.setTimeout(() => {
document.documentElement.classList.remove('ft-theme-transition');
document.body.classList.remove('ft-theme-transition');
}, 1000);
}
mode.value = themeName.toLowerCase() === 'bootstrap' ? 'light' : 'dark';
}
// Save the theme as localstorage
settingsStore.currentTheme = themeName;

View File

@ -3,10 +3,12 @@
v-model="plotStore.plotConfigName"
:allow-edit="allowEdit"
:allow-add="allowEdit"
:allow-duplicate="allowEdit"
editable-name="plot configuration"
@rename="plotStore.renamePlotConfig"
@delete="plotStore.deletePlotConfig"
@new="plotStore.newPlotConfig"
@duplicate="plotStore.duplicatePlotConfig"
>
<b-form-select
v-model="plotStore.plotConfigName"

View File

@ -1,22 +1,31 @@
<template>
<div class="d-flex flex-row">
<div class="flex-grow-1">
<slot v-if="!editing"> </slot>
<slot v-if="mode === EditState.None"> </slot>
<b-form-input v-else v-model="localName" size="sm"> </b-form-input>
</div>
<div
class="flex-grow-2 mt-auto d-flex gap-1 ms-1"
:class="alignVertical ? 'flex-column' : 'flex-row'"
>
<template v-if="allowEdit && !(addNew || editing)">
<template v-if="allowEdit && mode === EditState.None">
<b-button
size="sm"
variant="secondary"
:title="`Edit this ${editableName}.`"
@click="editing = true"
@click="mode = EditState.Editing"
>
<i-mdi-pencil />
</b-button>
<b-button
v-if="allowDuplicate"
size="sm"
variant="secondary"
:title="`Duplicate ${editableName}.`"
@click="duplicate"
>
<i-mdi-content-copy />
</b-button>
<b-button
size="sm"
variant="secondary"
@ -27,14 +36,14 @@
</b-button>
</template>
<b-button
v-if="allowAdd && !(addNew || editing)"
v-if="allowAdd && mode === EditState.None"
size="sm"
:title="`Add new ${editableName}.`"
variant="primary"
@click="addNewClick"
><i-mdi-plus-box-outline />
</b-button>
<template v-if="addNew || editing">
<template v-if="mode !== EditState.None">
<b-button
size="sm"
:title="`Add new '${editableName}`"
@ -67,6 +76,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
allowDuplicate: {
type: Boolean,
default: false,
},
editableName: {
type: String,
required: true,
@ -78,26 +91,37 @@ const props = defineProps({
});
const emit = defineEmits<{
(e: 'delete', value: string): void;
(e: 'new', value: string): void;
(e: 'rename', oldName: string, newName: string): void;
delete: [value: string];
new: [value: string];
duplicate: [oldName: string, newName: string];
rename: [oldName: string, newName: string];
}>();
const addNew = ref(false);
enum EditState {
None,
Editing,
Adding,
Duplicating,
}
const localName = ref<string>(props.modelValue);
const editing = ref<boolean>(false);
const mode = ref<EditState>(EditState.None);
function abort() {
editing.value = false;
addNew.value = false;
mode.value = EditState.None;
localName.value = props.modelValue;
}
function duplicate() {
localName.value = localName.value + ' (copy)';
mode.value = EditState.Duplicating;
}
function addNewClick() {
localName.value = '';
addNew.value = true;
editing.value = true;
mode.value = EditState.Adding;
}
watch(
() => props.modelValue,
() => {
@ -106,13 +130,14 @@ watch(
);
function saveNewName() {
editing.value = false;
if (addNew.value) {
addNew.value = false;
if (mode.value === EditState.Adding) {
emit('new', localName.value);
} else if (mode.value === EditState.Duplicating) {
emit('duplicate', props.modelValue, localName.value);
} else {
// Editing
emit('rename', props.modelValue, localName.value);
}
mode.value = EditState.None;
}
</script>

View File

@ -37,6 +37,12 @@ import {
BotDescriptor,
BgTaskStarted,
BackgroundTaskStatus,
Exchange,
ExchangeListResult,
FreqAIModelListResult,
PairlistEvalResponse,
PairlistsPayload,
PairlistsResponse,
} from '@/types';
import axios, { AxiosResponse } from 'axios';
import { defineStore } from 'pinia';
@ -44,12 +50,6 @@ import { showAlert } from './alerts';
import { useWebSocket } from '@vueuse/core';
import { FTWsMessage, FtWsMessageTypes } from '@/types/wsMessageTypes';
import { showNotification } from '@/shared/notifications';
import {
FreqAIModelListResult,
PairlistEvalResponse,
PairlistsPayload,
PairlistsResponse,
} from '../types';
export function createBotSubStore(botId: string, botName: string) {
const userService = useUserService(botId);
@ -91,6 +91,7 @@ export function createBotSubStore(botId: string, botName: string) {
strategyPlotConfig: undefined as PlotConfig | undefined,
strategyList: [] as string[],
freqaiModelList: [] as string[],
exchangeList: [] as Exchange[],
strategy: {} as StrategyResult,
pairlist: [] as string[],
currentLocks: undefined as LockResponse | undefined,
@ -448,6 +449,16 @@ export function createBotSubStore(botId: string, botName: string) {
return Promise.reject(error);
}
},
async getExchangeList() {
try {
const { data } = await api.get<ExchangeListResult>('/exchanges');
this.exchangeList = data.exchanges;
return Promise.resolve(data.exchanges);
} catch (error) {
console.error(error);
return Promise.reject(error);
}
},
async getAvailablePairs(payload: AvailablePairPayload) {
try {
const { data } = await api.get<AvailablePairResult>('/available_pairs', {

View File

@ -72,6 +72,11 @@ export const usePlotConfigStore = defineStore('plotConfig', {
this.editablePlotConfig = deepClone(this.customPlotConfigs[this.plotConfigName]);
}
},
duplicatePlotConfig(oldName: string, newName: string) {
console.log(oldName, newName);
this.customPlotConfigs[newName] = deepClone(this.customPlotConfigs[oldName]);
this.plotConfigChanged(newName);
},
},
persist: {
key: FT_PLOT_CONFIG_KEY,

View File

@ -2,3 +2,6 @@
// $body-bg: rgb(42, 42, 49);
$font-size-base: 0.9rem;
$primary: #0089a1;
$body-bg-dark: #121212;
$body-color-dark: #dedede;

View File

@ -41,7 +41,7 @@
font-size: 0.8rem;
}
[data-theme="dark"] {
[data-bs-theme="dark"] {
$bg-dark: rgb(18, 18, 18);
$bg-darker: darken($bg-dark, 5%);
@ -235,11 +235,14 @@
background-color: unset !important;
}
html.ft-theme-transition,
html.ft-theme-transition *,
html.ft-theme-transition *:before,
html.ft-theme-transition *:after {
transition: background 750ms ease-in-out,
border-color 750ms ease-in-out;
body.ft-theme-transition,
body.ft-theme-transition *,
body.ft-theme-transition *:before,
body.ft-theme-transition *:after {
transition:
background 750ms ease-in-out,
border-color 750ms ease-in-out,
background-color 750ms ease-in-out,
;
transition-delay: 0 !important;
}

18
src/types/exchange.ts Normal file
View File

@ -0,0 +1,18 @@
import { MarginMode, TradingMode } from './types';
export interface TradeMode {
trading_mode: TradingMode;
margin_mode: MarginMode;
}
export interface Exchange {
name: string;
valid: boolean;
supported: boolean;
comment: string;
trade_modes: TradeMode[];
}
export interface ExchangeListResult {
exchanges: Exchange[];
}

View File

@ -5,6 +5,7 @@ export * from './balance';
export * from './blacklist';
export * from './botComparison';
export * from './chart';
export * from './exchange';
export * from './daily';
export * from './gridLayout';
export * from './locks';

View File

@ -80,6 +80,12 @@ export enum TradingMode {
FUTURES = 'futures',
}
export enum MarginMode {
NONE = 'none',
ISOLATED = 'isolated',
// CROSS = 'cross',
}
export interface UnfilledTimeout {
/** @deprecated replaced by entry in 2.x */
buy?: number;