+import { useToast } from 'vue-toast-notification'
import {
ApplicationProtocol,
AuthenticationType,
`${this.uiServerConfiguration.secure === true ? ApplicationProtocol.WSS : ApplicationProtocol.WS}://${this.uiServerConfiguration.host}:${this.uiServerConfiguration.port}`,
protocols
)
- this.ws.onopen = openEvent => {
- console.info('WebSocket opened', openEvent)
+ this.ws.onopen = () => {
+ useToast().success(
+ `WebSocket to UI server '${this.uiServerConfiguration.host}' successfully opened`
+ )
}
this.ws.onmessage = this.responseHandler.bind(this)
this.ws.onerror = errorEvent => {
- console.error('WebSocket error: ', errorEvent)
+ useToast().error(`Error in WebSocket to UI server '${this.uiServerConfiguration.host}'`)
+ console.error(
+ `Error in WebSocket to UI server '${this.uiServerConfiguration.host}'`,
+ errorEvent
+ )
}
- this.ws.onclose = closeEvent => {
- console.info('WebSocket closed: ', closeEvent)
+ this.ws.onclose = () => {
+ useToast().info(`WebSocket to UI server '${this.uiServerConfiguration.host}' closed`)
}
}
}
return changedValue
}
+
+export const setToLocalStorage = <T>(key: string, value: T): void => {
+ localStorage.setItem(key, JSON.stringify(value))
+}
+
+export const getFromLocalStorage = <T>(key: string, defaultValue: T): T => {
+ const item = localStorage.getItem(key)
+ return item != null ? (JSON.parse(item) as T) : defaultValue
+}
export { UIClient } from './UIClient'
-export { convertToBoolean, convertToInt } from './Utils'
+export { convertToBoolean, convertToInt, getFromLocalStorage, setToLocalStorage } from './Utils'
-import { createApp } from 'vue'
+import { type App as AppType, createApp } from 'vue'
import ToastPlugin from 'vue-toast-notification'
import type { ConfigurationData, ResponsePayload } from '@/types'
import { router } from '@/router'
-import { UIClient } from '@/composables'
+import { UIClient, getFromLocalStorage, setToLocalStorage } from '@/composables'
import App from '@/App.vue'
import 'vue-toast-notification/dist/theme-bootstrap.css'
-const initializeApp = (config: ConfigurationData) => {
- const app = createApp(App)
+const app = createApp(App)
+
+const initializeApp = (app: AppType, config: ConfigurationData) => {
app.config.errorHandler = (error, instance, info) => {
console.error('Error:', error)
console.info('Vue instance:', instance)
console.info('Error info:', info)
// TODO: add code for UI notifications or other error handling logic
}
- app.config.globalProperties.$configuration = config
- app.config.globalProperties.$chargingStations = []
- app.config.globalProperties.$uiClient = UIClient.getInstance(
- app.config.globalProperties.$configuration.uiServer
- )
- app.config.globalProperties.$uiClient.registerWSEventListener('open', () => {
- app.config.globalProperties.$uiClient
- .listChargingStations()
- .then((response: ResponsePayload) => {
- app.config.globalProperties.$chargingStations = response.chargingStations
- })
- .catch((error: Error) => {
- // TODO: add code for UI notifications or other error handling logic
- console.error('Error at fetching charging stations:', error)
- })
- .finally(() => {
- app.use(router).use(ToastPlugin).mount('#app')
- })
- })
+ if (!Array.isArray(config.uiServer)) {
+ config.uiServer = [config.uiServer]
+ }
+ if (app.config.globalProperties.$configuration == null) {
+ app.config.globalProperties.$configuration = config
+ }
+ if (!Array.isArray(app.config.globalProperties.$chargingStations)) {
+ app.config.globalProperties.$chargingStations = []
+ }
+ if (
+ getFromLocalStorage<number | undefined>('uiServerConfigurationIndex', undefined) == null ||
+ getFromLocalStorage<number>('uiServerConfigurationIndex', 0) >
+ app.config.globalProperties.$configuration.uiServer.length - 1
+ ) {
+ setToLocalStorage<number>('uiServerConfigurationIndex', 0)
+ }
+ if (app.config.globalProperties.$uiClient == null) {
+ app.config.globalProperties.$uiClient = UIClient.getInstance(
+ app.config.globalProperties.$configuration.uiServer[
+ getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
+ ]
+ )
+ app.config.globalProperties.$uiClient.registerWSEventListener('open', () => {
+ app.config.globalProperties.$uiClient
+ .listChargingStations()
+ .then((response: ResponsePayload) => {
+ app.config.globalProperties.$chargingStations = response.chargingStations
+ })
+ .catch((error: Error) => {
+ // TODO: add code for UI notifications or other error handling logic
+ console.error('Error at fetching charging stations:', error)
+ })
+ .finally(() => {
+ app.use(router).use(ToastPlugin).mount('#app')
+ })
+ })
+ }
}
fetch('/config.json')
.json()
.then(config => {
try {
- initializeApp(config)
+ initializeApp(app, config)
} catch (error) {
// TODO: add code for UI notifications or other error handling logic
console.error('Error at initializing app:', error)
import type { AuthenticationType, Protocol, ProtocolVersion } from './UIProtocol'
export type ConfigurationData = {
- uiServer: UIServerConfigurationSection
+ uiServer: UIServerConfigurationSection | UIServerConfigurationSection[]
}
export type UIServerConfigurationSection = {
<template>
<Container id="charging-stations-container">
+ <Container id="ui-server-container">
+ <select
+ v-show="Array.isArray(uiServerConfigurations) && uiServerConfigurations.length > 1"
+ id="ui-server-selector"
+ v-model="state.uiServerIndex"
+ @change="
+ () => {
+ try {
+ if (
+ getFromLocalStorage<number>('uiServerConfigurationIndex', 0) !== state.uiServerIndex
+ ) {
+ setToLocalStorage<number>('uiServerConfigurationIndex', state.uiServerIndex)
+ app!.appContext.config.globalProperties.$uiClient.setConfiguration(
+ app?.appContext.config.globalProperties.$configuration.uiServer[
+ getFromLocalStorage<number>('uiServerConfigurationIndex', state.uiServerIndex)
+ ]
+ )
+ }
+ } catch (error) {
+ $toast.error('Error at changing UI server configuration')
+ console.error('Error at changing UI server configuration:', error)
+ }
+ }
+ "
+ >
+ <option
+ v-for="uiServerConfiguration in uiServerConfigurations"
+ :value="uiServerConfiguration.index"
+ >
+ {{ uiServerConfiguration.configuration.host }}
+ </option>
+ </select>
+ </Container>
<Container id="buttons-container">
<Button @click="startSimulator()">Start Simulator</Button>
<Button @click="stopSimulator()">Stop Simulator</Button>
import { getCurrentInstance, reactive } from 'vue'
import { useToast } from 'vue-toast-notification'
import CSTable from '@/components/charging-stations/CSTable.vue'
-import type { ResponsePayload } from '@/types'
+import type { ResponsePayload, UIServerConfigurationSection } from '@/types'
import Container from '@/components/Container.vue'
import ReloadButton from '@/components/buttons/ReloadButton.vue'
import Button from '@/components/buttons/Button.vue'
+import { getFromLocalStorage, setToLocalStorage } from '@/composables'
const state = reactive({
- isLoading: false
+ isLoading: false,
+ uiServerIndex: getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
})
const app = getCurrentInstance()
const uiClient = app?.appContext.config.globalProperties.$uiClient
+const uiServerConfigurations: { configuration: UIServerConfigurationSection; index: number }[] =
+ app?.appContext.config.globalProperties.$configuration.uiServer.map(
+ (configuration: UIServerConfigurationSection, index: number) => ({
+ configuration,
+ index
+ })
+ )
const $toast = useToast()
flex-direction: column;
}
+#ui-server-container {
+ display: flex;
+ flex-direction: row;
+}
+
+#ui-server-selector {
+ width: 100%;
+ text-align: center;
+}
+
#buttons-container {
display: flex;
flex-direction: row;