mirror of
https://github.com/freqtrade/frequi.git
synced 2024-11-25 20:45:15 +00:00
parent
2e803a0d57
commit
385a7fca11
|
@ -19,6 +19,7 @@
|
|||
"date-fns": "^2.22.1",
|
||||
"date-fns-tz": "^1.1.4",
|
||||
"echarts": "^5.1.0",
|
||||
"favico.js": "^0.3.10",
|
||||
"humanize-duration": "^3.27.0",
|
||||
"vue": "^2.6.14",
|
||||
"vue-class-component": "^7.2.5",
|
||||
|
|
|
@ -54,9 +54,12 @@ import userService from '@/shared/userService';
|
|||
import BootswatchThemeSelect from '@/components/BootswatchThemeSelect.vue';
|
||||
import { LayoutActions, LayoutGetters } from '@/store/modules/layout';
|
||||
import { BotStoreGetters } from '@/store/modules/ftbot';
|
||||
import Favico from 'favico.js';
|
||||
import { SettingsGetters } from '@/store/modules/settings';
|
||||
|
||||
const ftbot = namespace('ftbot');
|
||||
const layoutNs = namespace('layout');
|
||||
const uiSettingsNs = namespace('uiSettings');
|
||||
|
||||
@Component({
|
||||
components: { LoginModal, BootswatchThemeSelect },
|
||||
|
@ -74,6 +77,8 @@ export default class NavBar extends Vue {
|
|||
|
||||
@ftbot.Getter [BotStoreGetters.botName]: string;
|
||||
|
||||
@ftbot.Getter [BotStoreGetters.openTradeCount]: number;
|
||||
|
||||
@layoutNs.Getter [LayoutGetters.getLayoutLocked]: boolean;
|
||||
|
||||
@layoutNs.Action [LayoutActions.resetDashboardLayout];
|
||||
|
@ -82,6 +87,10 @@ export default class NavBar extends Vue {
|
|||
|
||||
@layoutNs.Action [LayoutActions.setLayoutLocked];
|
||||
|
||||
@uiSettingsNs.Getter [SettingsGetters.openTradesInTitle]: string;
|
||||
|
||||
favicon: Favico | undefined = undefined;
|
||||
|
||||
mounted() {
|
||||
this.ping();
|
||||
this.pingInterval = window.setInterval(this.ping, 60000);
|
||||
|
@ -103,10 +112,28 @@ export default class NavBar extends Vue {
|
|||
}
|
||||
|
||||
set layoutLockedLocal(value: boolean) {
|
||||
console.log(value);
|
||||
this.setLayoutLocked(value);
|
||||
}
|
||||
|
||||
setOpenTradesAsPill(tradeCount: number) {
|
||||
console.log('setPill', tradeCount);
|
||||
if (!this.favicon) {
|
||||
this.favicon = new Favico({
|
||||
animation: 'none',
|
||||
// position: 'up',
|
||||
// fontStyle: 'normal',
|
||||
// bgColor: '#',
|
||||
// textColor: '#FFFFFF',
|
||||
});
|
||||
}
|
||||
if (tradeCount !== 0 && this.openTradesInTitle === 'showPill') {
|
||||
this.favicon.badge(tradeCount);
|
||||
} else {
|
||||
this.favicon.reset();
|
||||
console.log('reset');
|
||||
}
|
||||
}
|
||||
|
||||
resetDynamicLayout(): void {
|
||||
const route = this.$router.currentRoute.path;
|
||||
console.log(`resetLayout called for ${route}`);
|
||||
|
@ -121,14 +148,37 @@ export default class NavBar extends Vue {
|
|||
}
|
||||
}
|
||||
|
||||
setTitle() {
|
||||
let title = 'freqUI';
|
||||
if (this.openTradesInTitle === 'asTitle') {
|
||||
title = `(${this.openTradeCount}) ${title}`;
|
||||
}
|
||||
if (this.botName) {
|
||||
title = `${title} - ${this.botName}`;
|
||||
}
|
||||
document.title = title;
|
||||
}
|
||||
|
||||
@Watch(BotStoreGetters.botName)
|
||||
botnameChanged() {
|
||||
if (this.botName) {
|
||||
document.title = `freqUI - ${this.botName}`;
|
||||
} else {
|
||||
document.title = 'freqUI';
|
||||
this.setTitle();
|
||||
}
|
||||
|
||||
@Watch(BotStoreGetters.openTradeCount)
|
||||
openTradeCountChanged() {
|
||||
console.log('openTradeCount changed');
|
||||
if (this.openTradesInTitle === 'showPill') {
|
||||
this.setOpenTradesAsPill(this.openTradeCount);
|
||||
} else if (this.openTradesInTitle === 'asTitle') {
|
||||
this.setTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Watch(SettingsGetters.openTradesInTitle)
|
||||
openTradesSettingChanged() {
|
||||
this.setTitle();
|
||||
this.setOpenTradesAsPill(this.openTradeCount);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -31,6 +31,11 @@ const routes: Array<RouteConfig> = [
|
|||
name: 'Freqtrade Dashboard',
|
||||
component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Dashboard.vue'),
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
name: 'Freqtrade Settings',
|
||||
component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Settings.vue'),
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
|
|
|
@ -7,6 +7,7 @@ import { AxiosInstance } from 'axios';
|
|||
import ftbotModule, { BotStoreGetters } from './modules/ftbot';
|
||||
import alertsModule from './modules/alerts';
|
||||
import layoutModule from './modules/layout';
|
||||
import settingsModule from './modules/settings';
|
||||
|
||||
const AUTO_REFRESH = 'ft_auto_refresh';
|
||||
|
||||
|
@ -38,6 +39,7 @@ export default new Vuex.Store({
|
|||
ftbot: ftbotModule,
|
||||
alerts: alertsModule,
|
||||
layout: layoutModule,
|
||||
uiSettings: settingsModule,
|
||||
},
|
||||
mutations: {
|
||||
setPing(state, ping) {
|
||||
|
|
|
@ -35,6 +35,7 @@ import { showAlert } from '../alerts';
|
|||
export enum BotStoreGetters {
|
||||
botName = 'botName',
|
||||
openTrades = 'openTrades',
|
||||
openTradeCount = 'openTradeCount',
|
||||
tradeDetail = 'tradeDetail',
|
||||
selectedPair = 'selectedPair',
|
||||
closedTrades = 'closedTrades',
|
||||
|
@ -64,6 +65,9 @@ export default {
|
|||
[BotStoreGetters.openTrades](state: FtbotStateType): Trade[] {
|
||||
return state.openTrades;
|
||||
},
|
||||
[BotStoreGetters.openTradeCount](state: FtbotStateType): number {
|
||||
return state.openTrades.length;
|
||||
},
|
||||
[BotStoreGetters.allTrades](state: FtbotStateType): Trade[] {
|
||||
return [...state.openTrades, ...state.trades];
|
||||
},
|
||||
|
@ -115,6 +119,7 @@ export default {
|
|||
state.tradeCount = tradesCount;
|
||||
},
|
||||
updateOpenTrades(state: FtbotStateType, trades) {
|
||||
console.log(`Update open trade length ${trades.length}`);
|
||||
state.openTrades = trades;
|
||||
},
|
||||
updateLocks(state: FtbotStateType, locks: LockResponse) {
|
||||
|
|
51
src/store/modules/settings.ts
Normal file
51
src/store/modules/settings.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
const STORE_UI_SETTINGS = 'ftUISettings';
|
||||
|
||||
export enum SettingsGetters {
|
||||
openTradesInTitle = 'openTradesInTitle',
|
||||
}
|
||||
|
||||
export enum SettingsActions {
|
||||
setOpenTradesInTitle = 'setOpenTradesInTitle',
|
||||
}
|
||||
|
||||
export enum SettingsMutations {
|
||||
setOpenTrades = 'setOpenTrades',
|
||||
}
|
||||
|
||||
function getSettings() {
|
||||
const fromStore = localStorage.getItem(STORE_UI_SETTINGS);
|
||||
if (fromStore) {
|
||||
return JSON.parse(fromStore);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
const storedSettings = getSettings();
|
||||
|
||||
function updateSetting(key: string, value: string) {
|
||||
const settings = getSettings() || {};
|
||||
settings[key] = value;
|
||||
localStorage.setItem(STORE_UI_SETTINGS, JSON.stringify(settings));
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
openTradesInTitle: storedSettings?.openTradesInTitle || 'showPill',
|
||||
},
|
||||
getters: {
|
||||
[SettingsGetters.openTradesInTitle](state) {
|
||||
return state.openTradesInTitle;
|
||||
},
|
||||
},
|
||||
mutations: {
|
||||
[SettingsMutations.setOpenTrades](state, value: string) {
|
||||
state.openTradesInTitle = value;
|
||||
updateSetting('openTradesInTitle', value);
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
[SettingsActions.setOpenTradesInTitle]({ commit }, locked: boolean) {
|
||||
commit(SettingsMutations.setOpenTrades, locked);
|
||||
},
|
||||
},
|
||||
};
|
|
@ -7,6 +7,8 @@
|
|||
:margin="[5, 5]"
|
||||
:is-resizable="!getLayoutLocked"
|
||||
:is-draggable="!getLayoutLocked"
|
||||
responsive
|
||||
prevent-collision
|
||||
@layout-updated="layoutUpdatedEvent"
|
||||
>
|
||||
<GridItem
|
||||
|
|
68
src/views/Settings.vue
Normal file
68
src/views/Settings.vue
Normal file
|
@ -0,0 +1,68 @@
|
|||
<template>
|
||||
<div class="container mt-3">
|
||||
<b-card header="FreqUI Settings">
|
||||
<div class="text-left">
|
||||
<b-form-group
|
||||
description="Lock dynamic layouts, so they cannot move anymore.\nCan also be set from the navbar at the top."
|
||||
>
|
||||
<b-checkbox v-model="layoutLockedLocal">Lock layout</b-checkbox>
|
||||
</b-form-group>
|
||||
<b-form-group
|
||||
label="Show open trades in header"
|
||||
description="Decide if open trades should be visualized"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="openTradesVisualization"
|
||||
:options="openTradesOptions"
|
||||
></b-form-select>
|
||||
</b-form-group>
|
||||
</div>
|
||||
</b-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { LayoutActions, LayoutGetters } from '@/store/modules/layout';
|
||||
import { SettingsActions, SettingsGetters } from '@/store/modules/settings';
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import { namespace } from 'vuex-class';
|
||||
|
||||
const layoutNs = namespace('layout');
|
||||
const uiSettingsNs = namespace('uiSettings');
|
||||
|
||||
@Component({})
|
||||
export default class Template extends Vue {
|
||||
@layoutNs.Getter [LayoutGetters.getLayoutLocked]: boolean;
|
||||
|
||||
@layoutNs.Action [LayoutActions.setLayoutLocked];
|
||||
|
||||
@uiSettingsNs.Getter [SettingsGetters.openTradesInTitle]: string;
|
||||
|
||||
@uiSettingsNs.Action [SettingsActions.setOpenTradesInTitle];
|
||||
|
||||
openTradesOptions = [
|
||||
{ value: 'showPill', text: 'Show pill in icon' },
|
||||
{ value: 'asTitle', text: 'Show in title' },
|
||||
{ value: 'noOpenTrades', text: "Don't show open trades in header" },
|
||||
];
|
||||
|
||||
get openTradesVisualization() {
|
||||
return this.openTradesInTitle;
|
||||
}
|
||||
|
||||
set openTradesVisualization(value: string) {
|
||||
console.log('show_open_trades', value);
|
||||
this.setOpenTradesInTitle(value);
|
||||
}
|
||||
|
||||
get layoutLockedLocal() {
|
||||
return this.getLayoutLocked;
|
||||
}
|
||||
|
||||
set layoutLockedLocal(value: boolean) {
|
||||
this.setLayoutLocked(value);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -4980,6 +4980,11 @@ fastq@^1.6.0:
|
|||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
favico.js@^0.3.10:
|
||||
version "0.3.10"
|
||||
resolved "https://registry.yarnpkg.com/favico.js/-/favico.js-0.3.10.tgz#80586e27a117f24a8d51c18a99bdc714d4339301"
|
||||
integrity sha1-gFhuJ6EX8kqNUcGKmb3HFNQzkwE=
|
||||
|
||||
faye-websocket@^0.11.3:
|
||||
version "0.11.3"
|
||||
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e"
|
||||
|
|
Loading…
Reference in New Issue
Block a user