mirror of
https://github.com/freqtrade/frequi.git
synced 2024-11-23 11:35:14 +00:00
Store botlist as objects, not string list
This commit is contained in:
parent
f346f49e60
commit
1c4e2aed54
|
@ -4,12 +4,12 @@
|
||||||
<b-list-group>
|
<b-list-group>
|
||||||
<b-list-group-item
|
<b-list-group-item
|
||||||
v-for="bot in allAvailableBots"
|
v-for="bot in allAvailableBots"
|
||||||
:key="bot"
|
:key="bot.botId"
|
||||||
button
|
button
|
||||||
:active="bot === selectedBot"
|
:active="bot.botId === selectedBot"
|
||||||
@click="selectBot(bot)"
|
@click="selectBot(bot.botId)"
|
||||||
>
|
>
|
||||||
{{ bot }}
|
{{ bot.botName || bot.botId }}
|
||||||
<b-button class="btn-xs ml-1" size="sm" title="Delete trade" @click="clickRemoveBot(bot)">
|
<b-button class="btn-xs ml-1" size="sm" title="Delete trade" @click="clickRemoveBot(bot)">
|
||||||
<EditIcon :size="16" title="Delete trade" />
|
<EditIcon :size="16" title="Delete trade" />
|
||||||
</b-button>
|
</b-button>
|
||||||
|
@ -29,6 +29,7 @@ import { MultiBotStoreGetters } from '@/store/modules/botStoreWrapper';
|
||||||
import LoginModal from '@/views/LoginModal.vue';
|
import LoginModal from '@/views/LoginModal.vue';
|
||||||
import EditIcon from 'vue-material-design-icons/Cog.vue';
|
import EditIcon from 'vue-material-design-icons/Cog.vue';
|
||||||
import DeleteIcon from 'vue-material-design-icons/Delete.vue';
|
import DeleteIcon from 'vue-material-design-icons/Delete.vue';
|
||||||
|
import { BotDescriptor, BotDescriptors } from '@/types';
|
||||||
|
|
||||||
const ftbot = namespace('ftbot');
|
const ftbot = namespace('ftbot');
|
||||||
|
|
||||||
|
@ -36,17 +37,17 @@ const ftbot = namespace('ftbot');
|
||||||
export default class BotList extends Vue {
|
export default class BotList extends Vue {
|
||||||
@ftbot.Getter [MultiBotStoreGetters.selectedBot]: string;
|
@ftbot.Getter [MultiBotStoreGetters.selectedBot]: string;
|
||||||
|
|
||||||
@ftbot.Getter [MultiBotStoreGetters.allAvailableBots]: string[];
|
@ftbot.Getter [MultiBotStoreGetters.allAvailableBots]: BotDescriptors;
|
||||||
|
|
||||||
@ftbot.Action removeBot;
|
@ftbot.Action removeBot;
|
||||||
|
|
||||||
@ftbot.Action selectBot;
|
@ftbot.Action selectBot;
|
||||||
|
|
||||||
clickRemoveBot(botId) {
|
clickRemoveBot(botId: BotDescriptor) {
|
||||||
//
|
//
|
||||||
this.$bvModal.msgBoxConfirm(`Really remove (logout) from ${botId}?`).then((value: boolean) => {
|
this.$bvModal.msgBoxConfirm(`Really remove (logout) from ${botId}?`).then((value: boolean) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
this.removeBot(botId);
|
this.removeBot(botId.botId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ import { Component, Vue, Emit, Prop } from 'vue-property-decorator';
|
||||||
import { Action, namespace } from 'vuex-class';
|
import { Action, namespace } from 'vuex-class';
|
||||||
import { useUserService } from '@/shared/userService';
|
import { useUserService } from '@/shared/userService';
|
||||||
|
|
||||||
import { AuthPayload } from '@/types';
|
import { AuthPayload, BotDescriptor } from '@/types';
|
||||||
import { MultiBotStoreGetters } from '@/store/modules/botStoreWrapper';
|
import { MultiBotStoreGetters } from '@/store/modules/botStoreWrapper';
|
||||||
|
|
||||||
const defaultURL = window.location.origin || 'http://localhost:8080';
|
const defaultURL = window.location.origin || 'http://localhost:8080';
|
||||||
|
@ -85,7 +85,8 @@ export default class Login extends Vue {
|
||||||
|
|
||||||
@ftbot.Getter [MultiBotStoreGetters.nextBotId]: string;
|
@ftbot.Getter [MultiBotStoreGetters.nextBotId]: string;
|
||||||
|
|
||||||
@ftbot.Action addBot;
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
@ftbot.Action addBot!: (payload: BotDescriptor) => void;
|
||||||
|
|
||||||
@Prop({ default: false }) inModal!: boolean;
|
@Prop({ default: false }) inModal!: boolean;
|
||||||
|
|
||||||
|
@ -148,7 +149,10 @@ export default class Login extends Vue {
|
||||||
userService
|
userService
|
||||||
.login(this.auth)
|
.login(this.auth)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.addBot(this.nextBotId);
|
this.addBot({
|
||||||
|
botName: this.auth.botName,
|
||||||
|
botId: this.nextBotId,
|
||||||
|
});
|
||||||
// TODO: Investigate how this needs to be done properly
|
// TODO: Investigate how this needs to be done properly
|
||||||
// setBaseUrl(userService.getAPIUrl());
|
// setBaseUrl(userService.getAPIUrl());
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import { AuthPayload, AuthStorage, AuthStorageMulti } from '@/types';
|
import { AuthPayload, BotDescriptors, AuthStorage, AuthStorageMulti } from '@/types';
|
||||||
|
|
||||||
const AUTH_LOGIN_INFO = 'auth_login_info';
|
const AUTH_LOGIN_INFO = 'auth_login_info';
|
||||||
const APIBASE = '/api/v1';
|
const APIBASE = '/api/v1';
|
||||||
|
@ -63,6 +63,18 @@ export class UserService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static getAvailableBots(): BotDescriptors {
|
||||||
|
const allInfo = UserService.getAllLoginInfos();
|
||||||
|
const response: BotDescriptors = {};
|
||||||
|
Object.entries(allInfo).forEach(([k, v]) => {
|
||||||
|
response[k] = {
|
||||||
|
botId: k,
|
||||||
|
botName: v.botName,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
public static getAvailableBotList(): string[] {
|
public static getAvailableBotList(): string[] {
|
||||||
const allInfo = UserService.getAllLoginInfos();
|
const allInfo = UserService.getAllLoginInfos();
|
||||||
return Object.keys(allInfo);
|
return Object.keys(allInfo);
|
||||||
|
@ -158,6 +170,7 @@ export class UserService {
|
||||||
* Call on startup to migrate old login info to new login
|
* Call on startup to migrate old login info to new login
|
||||||
*/
|
*/
|
||||||
public migrateLogin() {
|
public migrateLogin() {
|
||||||
|
// TODO: this is actually never called!
|
||||||
const AUTH_REFRESH_TOKEN = 'auth_ref_token'; // Legacy key - do not use
|
const AUTH_REFRESH_TOKEN = 'auth_ref_token'; // Legacy key - do not use
|
||||||
const AUTH_ACCESS_TOKEN = 'auth_access_token';
|
const AUTH_ACCESS_TOKEN = 'auth_access_token';
|
||||||
const AUTH_API_URL = 'auth_api_url';
|
const AUTH_API_URL = 'auth_api_url';
|
||||||
|
|
|
@ -143,8 +143,8 @@ const store = new Vuex.Store({
|
||||||
});
|
});
|
||||||
|
|
||||||
store.registerModule('ftbot', createBotStore(store));
|
store.registerModule('ftbot', createBotStore(store));
|
||||||
UserService.getAvailableBotList().forEach((e) => {
|
Object.entries(UserService.getAvailableBots()).forEach(([k, v]) => {
|
||||||
store.dispatch('ftbot/addBot', e);
|
store.dispatch('ftbot/addBot', v);
|
||||||
});
|
});
|
||||||
store.dispatch('ftbot/selectFirstBot');
|
store.dispatch('ftbot/selectFirstBot');
|
||||||
export default store;
|
export default store;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
import { BotDescriptor, BotDescriptors } from '@/types';
|
||||||
import { BotStoreActions, BotStoreGetters, createBotSubStore } from './ftbot';
|
import { BotStoreActions, BotStoreGetters, createBotSubStore } from './ftbot';
|
||||||
|
|
||||||
interface FTMultiBotState {
|
interface FTMultiBotState {
|
||||||
selectedBot: string;
|
selectedBot: string;
|
||||||
availableBots: string[];
|
availableBots: BotDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum MultiBotStoreGetters {
|
export enum MultiBotStoreGetters {
|
||||||
|
@ -15,29 +16,30 @@ export enum MultiBotStoreGetters {
|
||||||
export default function createBotStore(store) {
|
export default function createBotStore(store) {
|
||||||
const state: FTMultiBotState = {
|
const state: FTMultiBotState = {
|
||||||
selectedBot: '',
|
selectedBot: '',
|
||||||
availableBots: [],
|
availableBots: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
// All getters working on all bots should be prefixed with all.
|
// All getters working on all bots should be prefixed with all.
|
||||||
const getters = {
|
const getters = {
|
||||||
[MultiBotStoreGetters.hasBots](state: FTMultiBotState): boolean {
|
[MultiBotStoreGetters.hasBots](state: FTMultiBotState): boolean {
|
||||||
return state.availableBots.length > 0;
|
return Object.keys(state.availableBots).length > 0;
|
||||||
},
|
},
|
||||||
[MultiBotStoreGetters.selectedBot](state: FTMultiBotState): string {
|
[MultiBotStoreGetters.selectedBot](state: FTMultiBotState): string {
|
||||||
return state.selectedBot;
|
return state.selectedBot;
|
||||||
},
|
},
|
||||||
[MultiBotStoreGetters.allAvailableBots](state: FTMultiBotState): string[] {
|
[MultiBotStoreGetters.allAvailableBots](state: FTMultiBotState): BotDescriptors {
|
||||||
return state.availableBots;
|
return state.availableBots;
|
||||||
},
|
},
|
||||||
[MultiBotStoreGetters.nextBotId](state: FTMultiBotState): string {
|
[MultiBotStoreGetters.nextBotId](state: FTMultiBotState): string {
|
||||||
let botCount = state.availableBots.length;
|
let botCount = Object.keys(state.availableBots).length;
|
||||||
while (state.availableBots.includes(`ftbot.${botCount}`)) {
|
|
||||||
|
while (`ftbot.${botCount}` in state.availableBots) {
|
||||||
botCount += 1;
|
botCount += 1;
|
||||||
}
|
}
|
||||||
return `ftbot.${botCount}`;
|
return `ftbot.${botCount}`;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// Autocreate getters
|
// Autocreate getters from botStores
|
||||||
Object.keys(BotStoreGetters).forEach((e) => {
|
Object.keys(BotStoreGetters).forEach((e) => {
|
||||||
getters[e] = (state, getters) => {
|
getters[e] = (state, getters) => {
|
||||||
return getters[`${state.selectedBot}/${e}`];
|
return getters[`${state.selectedBot}/${e}`];
|
||||||
|
@ -46,37 +48,37 @@ export default function createBotStore(store) {
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
selectBot(state: FTMultiBotState, botId: string) {
|
selectBot(state: FTMultiBotState, botId: string) {
|
||||||
if (state.availableBots.includes(botId)) {
|
if (botId in state.availableBots) {
|
||||||
state.selectedBot = botId;
|
state.selectedBot = botId;
|
||||||
} else {
|
} else {
|
||||||
console.warn(`Botid ${botId} not available, but selected`);
|
console.warn(`Botid ${botId} not available, but selected.`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addBot(state: FTMultiBotState, botId: string) {
|
addBot(state: FTMultiBotState, bot: BotDescriptor) {
|
||||||
state.availableBots = [...state.availableBots, botId];
|
state.availableBots[bot.botId] = bot;
|
||||||
},
|
},
|
||||||
removeBot(state: FTMultiBotState, botId: string) {
|
removeBot(state: FTMultiBotState, botId: string) {
|
||||||
const index = state.availableBots.indexOf(botId);
|
if (botId in state.availableBots) {
|
||||||
if (index > -1) {
|
delete state.availableBots[botId];
|
||||||
state.availableBots.splice(index, 1);
|
|
||||||
state.availableBots = [...state.availableBots];
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
// Actions automatically filled below
|
// Actions automatically filled below
|
||||||
addBot({ getters, commit }, botId: string) {
|
addBot({ getters, commit }, bot: BotDescriptor) {
|
||||||
if (getters.allAvailableBots.includes(botId)) {
|
if (Object.keys(getters.allAvailableBots).includes(bot.botId)) {
|
||||||
// throw 'Bot already present';
|
// throw 'Bot already present';
|
||||||
// TODO: handle error!
|
// TODO: handle error!
|
||||||
|
console.log('Bot already present');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
console.log('add bot', botId);
|
console.log('add bot', bot);
|
||||||
store.registerModule(['ftbot', botId], createBotSubStore(botId));
|
store.registerModule(['ftbot', bot.botId], createBotSubStore(bot.botId));
|
||||||
commit('addBot', botId);
|
commit('addBot', bot);
|
||||||
},
|
},
|
||||||
removeBot({ commit, getters, dispatch }, botId: string) {
|
removeBot({ commit, getters, dispatch }, botId: string) {
|
||||||
if (getters.allAvailableBots.includes(botId)) {
|
if (Object.keys(getters.allAvailableBots).includes(botId)) {
|
||||||
dispatch(`${botId}/logout`);
|
dispatch(`${botId}/logout`);
|
||||||
store.unregisterModule([`ftbot`, botId]);
|
store.unregisterModule([`ftbot`, botId]);
|
||||||
commit('removeBot', botId);
|
commit('removeBot', botId);
|
||||||
|
@ -86,14 +88,16 @@ export default function createBotStore(store) {
|
||||||
},
|
},
|
||||||
selectFirstBot({ commit, getters }) {
|
selectFirstBot({ commit, getters }) {
|
||||||
if (getters.hasBots) {
|
if (getters.hasBots) {
|
||||||
commit('selectBot', getters.allAvailableBots[0]);
|
const firstBot = Object.keys(getters.allAvailableBots)[0];
|
||||||
|
console.log(firstBot);
|
||||||
|
commit('selectBot', getters.allAvailableBots[firstBot].botId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectBot({ commit }, botId: string) {
|
selectBot({ commit }, botId: string) {
|
||||||
commit('selectBot', botId);
|
commit('selectBot', botId);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// Autocreate Actions
|
// Autocreate Actions from botstores
|
||||||
Object.keys(BotStoreActions).forEach((e) => {
|
Object.keys(BotStoreActions).forEach((e) => {
|
||||||
actions[e] = ({ state, dispatch, getters }, ...args) => {
|
actions[e] = ({ state, dispatch, getters }, ...args) => {
|
||||||
if (getters.hasBots) {
|
if (getters.hasBots) {
|
||||||
|
|
|
@ -15,3 +15,12 @@ export interface AuthStorage {
|
||||||
export interface AuthStorageMulti {
|
export interface AuthStorageMulti {
|
||||||
[key: string]: AuthStorage;
|
[key: string]: AuthStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BotDescriptor {
|
||||||
|
botName: string;
|
||||||
|
botId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BotDescriptors {
|
||||||
|
[key: string]: BotDescriptor;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user