mirror of
https://github.com/freqtrade/frequi.git
synced 2024-11-23 19:45:15 +00:00
Allow login to multiple bots
This commit is contained in:
parent
acd702dab3
commit
0955c21082
29
src/components/BotList.vue
Normal file
29
src/components/BotList.vue
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h3>Available bots</h3>
|
||||||
|
<div v-for="bot in allAvailableBots" :key="bot">
|
||||||
|
{{ bot }}
|
||||||
|
</div>
|
||||||
|
<LoginModal login-text="Add new bot" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
|
import { namespace } from 'vuex-class';
|
||||||
|
import { MultiBotStoreGetters } from '@/store/modules/botStoreWrapper';
|
||||||
|
import LoginModal from '@/views/LoginModal.vue';
|
||||||
|
|
||||||
|
const ftbot = namespace('ftbot');
|
||||||
|
|
||||||
|
@Component({ components: { LoginModal } })
|
||||||
|
export default class BotList extends Vue {
|
||||||
|
@ftbot.Getter [MultiBotStoreGetters.allAvailableBots]: string[];
|
||||||
|
|
||||||
|
clickAddBot() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -60,17 +60,23 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue, Emit, Prop } from 'vue-property-decorator';
|
import { Component, Vue, Emit, Prop } from 'vue-property-decorator';
|
||||||
import { Action } from 'vuex-class';
|
import { Action, namespace } from 'vuex-class';
|
||||||
import userService from '@/shared/userService';
|
import { useUserService } from '@/shared/userService';
|
||||||
|
|
||||||
import { AuthPayload } from '@/types';
|
import { AuthPayload } from '@/types';
|
||||||
|
import { MultiBotStoreGetters } from '@/store/modules/botStoreWrapper';
|
||||||
|
|
||||||
const defaultURL = window.location.origin || 'http://localhost:8080';
|
const defaultURL = window.location.origin || 'http://localhost:8080';
|
||||||
|
const ftbot = namespace('ftbot');
|
||||||
|
|
||||||
@Component({})
|
@Component({})
|
||||||
export default class Login extends Vue {
|
export default class Login extends Vue {
|
||||||
@Action setLoggedIn;
|
@Action setLoggedIn;
|
||||||
|
|
||||||
|
@ftbot.Getter [MultiBotStoreGetters.nextBotId]: string;
|
||||||
|
|
||||||
|
@ftbot.Action addBot;
|
||||||
|
|
||||||
@Prop({ default: false }) inModal!: boolean;
|
@Prop({ default: false }) inModal!: boolean;
|
||||||
|
|
||||||
$refs!: {
|
$refs!: {
|
||||||
|
@ -126,11 +132,12 @@ export default class Login extends Vue {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.errorMessage = '';
|
this.errorMessage = '';
|
||||||
|
const userService = useUserService(this.nextBotId);
|
||||||
// Push the name to submitted names
|
// Push the name to submitted names
|
||||||
userService
|
userService
|
||||||
.login(this.auth)
|
.login(this.auth)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.setLoggedIn(true);
|
this.addBot(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());
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class UserService {
|
||||||
* Stores info for current botId in the object of all bots.
|
* Stores info for current botId in the object of all bots.
|
||||||
*/
|
*/
|
||||||
private storeLoginInfo(loginInfo: AuthStorage): void {
|
private storeLoginInfo(loginInfo: AuthStorage): void {
|
||||||
const allInfo = this.getAllLoginInfos();
|
const allInfo = UserService.getAllLoginInfos();
|
||||||
allInfo[this.botId] = loginInfo;
|
allInfo[this.botId] = loginInfo;
|
||||||
localStorage.setItem(AUTH_LOGIN_INFO, JSON.stringify(allInfo));
|
localStorage.setItem(AUTH_LOGIN_INFO, JSON.stringify(allInfo));
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ export class UserService {
|
||||||
* Logout - removing info for this particular bot.
|
* Logout - removing info for this particular bot.
|
||||||
*/
|
*/
|
||||||
private removeLoginInfo(): void {
|
private removeLoginInfo(): void {
|
||||||
const info = this.getAllLoginInfos();
|
const info = UserService.getAllLoginInfos();
|
||||||
delete info[this.botId];
|
delete info[this.botId];
|
||||||
localStorage.setItem(AUTH_LOGIN_INFO, JSON.stringify(info));
|
localStorage.setItem(AUTH_LOGIN_INFO, JSON.stringify(info));
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ export class UserService {
|
||||||
* Retrieve full logininfo object (for all registered bots)
|
* Retrieve full logininfo object (for all registered bots)
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
private getAllLoginInfos(): AuthStorageMulti {
|
private static getAllLoginInfos(): AuthStorageMulti {
|
||||||
const info = JSON.parse(localStorage.getItem(AUTH_LOGIN_INFO) || '{}');
|
const info = JSON.parse(localStorage.getItem(AUTH_LOGIN_INFO) || '{}');
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ export class UserService {
|
||||||
* @returns Login Info object
|
* @returns Login Info object
|
||||||
*/
|
*/
|
||||||
private getLoginInfo(): AuthStorage {
|
private getLoginInfo(): AuthStorage {
|
||||||
const info = this.getAllLoginInfos();
|
const info = UserService.getAllLoginInfos();
|
||||||
if (this.botId in info && 'apiUrl' in info[this.botId] && 'refreshToken' in info[this.botId]) {
|
if (this.botId in info && 'apiUrl' in info[this.botId] && 'refreshToken' in info[this.botId]) {
|
||||||
return info[this.botId];
|
return info[this.botId];
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,11 @@ export class UserService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static getAvailableBotList(): string[] {
|
||||||
|
const allInfo = UserService.getAllLoginInfos();
|
||||||
|
return Object.keys(allInfo);
|
||||||
|
}
|
||||||
|
|
||||||
public getAccessToken(): string {
|
public getAccessToken(): string {
|
||||||
return this.getLoginInfo().accessToken;
|
return this.getLoginInfo().accessToken;
|
||||||
}
|
}
|
||||||
|
@ -183,4 +188,4 @@ export function useUserService(botId: string) {
|
||||||
return userservice;
|
return userservice;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useUserService('ftbot.0');
|
// export default useUserService('ftbot.0');
|
||||||
|
|
|
@ -3,6 +3,7 @@ import Vuex from 'vuex';
|
||||||
|
|
||||||
import { getCurrentTheme, getTheme, storeCurrentTheme } from '@/shared/themes';
|
import { getCurrentTheme, getTheme, storeCurrentTheme } from '@/shared/themes';
|
||||||
import axios, { AxiosInstance } from 'axios';
|
import axios, { AxiosInstance } from 'axios';
|
||||||
|
import { UserService } from '@/shared/userService';
|
||||||
import createBotStore from './modules/botStoreWrapper';
|
import createBotStore from './modules/botStoreWrapper';
|
||||||
import { BotStoreGetters } from './modules/ftbot';
|
import { BotStoreGetters } from './modules/ftbot';
|
||||||
import alertsModule from './modules/alerts';
|
import alertsModule from './modules/alerts';
|
||||||
|
@ -142,5 +143,7 @@ const store = new Vuex.Store({
|
||||||
});
|
});
|
||||||
|
|
||||||
store.registerModule('ftbot', createBotStore(store));
|
store.registerModule('ftbot', createBotStore(store));
|
||||||
store.dispatch('ftbot/addBot', 'ftbot.0');
|
UserService.getAvailableBotList().forEach((e) => {
|
||||||
|
store.dispatch('ftbot/addBot', e);
|
||||||
|
});
|
||||||
export default store;
|
export default store;
|
||||||
|
|
|
@ -9,6 +9,7 @@ export enum MultiBotStoreGetters {
|
||||||
hasBots = 'hasBots',
|
hasBots = 'hasBots',
|
||||||
selectedBot = 'selectedBot',
|
selectedBot = 'selectedBot',
|
||||||
allAvailableBots = 'allAvailableBots',
|
allAvailableBots = 'allAvailableBots',
|
||||||
|
nextBotId = 'nextBotId',
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function createBotStore(store) {
|
export default function createBotStore(store) {
|
||||||
|
@ -28,6 +29,13 @@ export default function createBotStore(store) {
|
||||||
[MultiBotStoreGetters.allAvailableBots](state: FTMultiBotState): string[] {
|
[MultiBotStoreGetters.allAvailableBots](state: FTMultiBotState): string[] {
|
||||||
return state.availableBots;
|
return state.availableBots;
|
||||||
},
|
},
|
||||||
|
[MultiBotStoreGetters.nextBotId](state: FTMultiBotState): string {
|
||||||
|
let botCount = state.availableBots.length;
|
||||||
|
while (`ftbot.${botCount}` in state.availableBots) {
|
||||||
|
botCount += 1;
|
||||||
|
}
|
||||||
|
return `ftbot.${botCount}`;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
// Autocreate getters
|
// Autocreate getters
|
||||||
Object.keys(BotStoreGetters).forEach((e) => {
|
Object.keys(BotStoreGetters).forEach((e) => {
|
||||||
|
@ -37,6 +45,13 @@ export default function createBotStore(store) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
|
selectBot(state: FTMultiBotState, botId: string) {
|
||||||
|
if (botId in state.availableBots) {
|
||||||
|
state.selectedBot = botId;
|
||||||
|
} else {
|
||||||
|
console.warn(`Botid ${botId} not available, but selected`);
|
||||||
|
}
|
||||||
|
},
|
||||||
addBot(state: FTMultiBotState, botId: string) {
|
addBot(state: FTMultiBotState, botId: string) {
|
||||||
state.availableBots = [...state.availableBots, botId];
|
state.availableBots = [...state.availableBots, botId];
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="home">
|
<div class="home">
|
||||||
|
<bot-list />
|
||||||
|
<hr />
|
||||||
<!-- <img alt="Freqtrade logo" src="../assets/freqtrade-logo.png" width="450px" class="my-5" /> -->
|
<!-- <img alt="Freqtrade logo" src="../assets/freqtrade-logo.png" width="450px" class="my-5" /> -->
|
||||||
<div alt="Freqtrade logo" class="logo-svg my-5 mx-auto" />
|
<div alt="Freqtrade logo" class="logo-svg my-5 mx-auto" />
|
||||||
<div>
|
<div>
|
||||||
|
@ -19,7 +21,11 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
@Component
|
import BotList from '@/components/BotList.vue';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: { BotList },
|
||||||
|
})
|
||||||
export default class Home extends Vue {}
|
export default class Home extends Vue {}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<b-button v-b-modal.modal-prevent-closing>Login</b-button>
|
<b-button v-b-modal.modal-prevent-closing>{{ loginText }}</b-button>
|
||||||
<b-modal id="modal-prevent-closing" ref="modal" title="Submit Your Name" @ok="handleOk">
|
<b-modal id="modal-prevent-closing" ref="modal" title="Submit Your Name" @ok="handleOk">
|
||||||
<Login id="loginForm" ref="loginForm" in-modal />
|
<Login id="loginForm" ref="loginForm" in-modal />
|
||||||
</b-modal>
|
</b-modal>
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
import Login from '@/components/Login.vue';
|
import Login from '@/components/Login.vue';
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ export default class LoginModal extends Vue {
|
||||||
loginForm: HTMLFormElement;
|
loginForm: HTMLFormElement;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@Prop({ required: false, default: 'Login', type: String }) loginText!: string;
|
||||||
|
|
||||||
resetLogin() {
|
resetLogin() {
|
||||||
// this.$refs.loginForm.resetLogin();
|
// this.$refs.loginForm.resetLogin();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user