build(deps-dev): apply updates
[e-mobility-charging-stations-simulator.git] / ui / web / src / views / ChargingStationsView.vue
index f500591a551c2c5332add353dded21d7647ddc5a..90433782b17a68b413e94cefb92776a3e333cbb2 100644 (file)
 <template>
-  <Container id="charging-stations">
-    <Button id="simulator-button" @click="startSimulator()">Start Simulator</Button>
-    <Button id="simulator-button" @click="stopSimulator()">Stop Simulator</Button>
-    <Container id="inputs-container">
-      <input
-        id="idtag-field"
-        v-model="state.idTag"
-        type="text"
-        name="idtag-field"
-        placeholder="RFID tag"
+  <Container id="charging-stations-container">
+    <Container
+      v-show="Array.isArray(uiServerConfigurations) && uiServerConfigurations.length > 1"
+      id="ui-server-container"
+    >
+      <select
+        id="ui-server-selector"
+        v-model="state.uiServerIndex"
+        @change="
+          () => {
+            if (
+              getFromLocalStorage<number>('uiServerConfigurationIndex', 0) !== state.uiServerIndex
+            ) {
+              app?.appContext.config.globalProperties.$uiClient.setConfiguration(
+                app?.appContext.config.globalProperties.$configuration.uiServer[state.uiServerIndex]
+              )
+              initializeWSEventListeners()
+              app?.appContext.config.globalProperties.$uiClient.registerWSEventListener(
+                'open',
+                () => {
+                  setToLocalStorage<number>('uiServerConfigurationIndex', state.uiServerIndex)
+                  delete app?.appContext.config.globalProperties.$templates
+                  $router.currentRoute.value.name !== 'charging-stations' &&
+                    $router.push({ name: 'charging-stations' })
+                },
+                { once: true }
+              )
+              app?.appContext.config.globalProperties.$uiClient.registerWSEventListener(
+                'error',
+                () => {
+                  state.uiServerIndex = getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
+                  app?.appContext.config.globalProperties.$uiClient.setConfiguration(
+                    app?.appContext.config.globalProperties.$configuration.uiServer[
+                      getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
+                    ]
+                  )
+                  initializeWSEventListeners()
+                },
+                { once: true }
+              )
+            }
+          }
+        "
+      >
+        <option
+          v-for="uiServerConfiguration in uiServerConfigurations"
+          :value="uiServerConfiguration.index"
+        >
+          {{ uiServerConfiguration.configuration.name ?? uiServerConfiguration.configuration.host }}
+        </option>
+      </select>
+    </Container>
+    <Container id="buttons-container">
+      <Button @click="startSimulator()">Start Simulator</Button>
+      <Button @click="stopSimulator()">Stop Simulator</Button>
+      <Button @click="$router.push({ name: 'add-charging-stations' })">
+        Add Charging Stations
+      </Button>
+      <ReloadButton
+        id="reload-button"
+        :loading="state.loading"
+        @click="loadChargingStations(() => (state.renderChargingStationsList = randomUUID()))"
       />
-      <ReloadButton id="reload-button" :loading="state.isLoading" @click="load()" />
     </Container>
-    <CSTable :charging-stations="state.chargingStations" :id-tag="state.idTag" />
+    <CSTable
+      v-show="
+        Array.isArray(app?.appContext.config.globalProperties.$chargingStations) &&
+        app?.appContext.config.globalProperties.$chargingStations.length > 0
+      "
+      :key="state.renderChargingStationsList"
+      :charging-stations="app?.appContext.config.globalProperties.$chargingStations"
+    />
   </Container>
 </template>
 
 <script setup lang="ts">
-import { onMounted, reactive } from 'vue'
+import { getCurrentInstance, onMounted, reactive } from 'vue'
+import { useToast } from 'vue-toast-notification'
 import CSTable from '@/components/charging-stations/CSTable.vue'
-import type { ChargingStationData } from '@/types'
+import type { ResponsePayload, UIServerConfigurationSection } from '@/types'
 import Container from '@/components/Container.vue'
 import ReloadButton from '@/components/buttons/ReloadButton.vue'
-import { UIClient } from '@/composables/UIClient'
+import Button from '@/components/buttons/Button.vue'
+import { getFromLocalStorage, setToLocalStorage } from '@/composables'
 
-const UIClientInstance = UIClient.getInstance()
+const randomUUID = (): `${string}-${string}-${string}-${string}-${string}` => {
+  return crypto.randomUUID()
+}
 
-onMounted(() => {
-  UIClientInstance.registerWSonOpenListener(load)
-})
+const app = getCurrentInstance()
 
-type State = {
-  isLoading: boolean
-  chargingStations: ChargingStationData[]
-  idTag: string
+const initializeWSEventListeners = () => {
+  app?.appContext.config.globalProperties.$uiClient.registerWSEventListener('open', () => {
+    loadChargingStations(() => (state.renderChargingStationsList = randomUUID()))
+  })
+  app?.appContext.config.globalProperties.$uiClient.registerWSEventListener('error', () => {
+    app.appContext.config.globalProperties.$chargingStations = []
+    state.renderChargingStationsList = randomUUID()
+  })
+  app?.appContext.config.globalProperties.$uiClient.registerWSEventListener('close', () => {
+    app.appContext.config.globalProperties.$chargingStations = []
+    state.renderChargingStationsList = randomUUID()
+  })
 }
 
-const state: State = reactive({
-  isLoading: false,
-  chargingStations: [],
-  idTag: ''
+onMounted(() => {
+  initializeWSEventListeners()
+})
+
+const state = reactive({
+  renderChargingStationsList: randomUUID(),
+  loading: false,
+  uiServerIndex: getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
 })
 
-async function load(): Promise<void> {
-  if (state.isLoading === true) return
-  state.isLoading = true
-  const listChargingStationsPayload = await UIClientInstance.listChargingStations()
-  state.chargingStations =
-    listChargingStationsPayload.chargingStations as unknown as ChargingStationData[]
-  state.isLoading = false
+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()
+
+const loadChargingStations = (renderCallback?: () => void): void => {
+  if (state.loading === false) {
+    state.loading = true
+    uiClient
+      .listChargingStations()
+      .then((response: ResponsePayload) => {
+        if (app != null) {
+          app.appContext.config.globalProperties.$chargingStations = response.chargingStations
+        }
+      })
+      .catch((error: Error) => {
+        if (app != null) {
+          app.appContext.config.globalProperties.$chargingStations = []
+        }
+        $toast.error('Error at fetching charging stations')
+        console.error('Error at fetching charging stations:', error)
+      })
+      .finally(() => {
+        if (renderCallback != null) {
+          renderCallback()
+        }
+        state.loading = false
+      })
+  }
 }
 
-function startSimulator(): void {
-  UIClientInstance.startSimulator()
+const startSimulator = (): void => {
+  uiClient
+    .startSimulator()
+    .then(() => {
+      $toast.success('Simulator successfully started')
+    })
+    .catch((error: Error) => {
+      $toast.error('Error at starting simulator')
+      console.error('Error at starting simulator:', error)
+    })
 }
-function stopSimulator(): void {
-  UIClientInstance.stopSimulator()
+const stopSimulator = (): void => {
+  uiClient
+    .stopSimulator()
+    .then(() => {
+      if (app != null) {
+        app.appContext.config.globalProperties.$chargingStations = []
+      }
+      $toast.success('Simulator successfully stopped')
+    })
+    .catch((error: Error) => {
+      $toast.error('Error at stopping simulator')
+      console.error('Error at stopping simulator:', error)
+    })
 }
 </script>
 
 <style>
-#charging-stations {
+#charging-stations-container {
   height: fit-content;
   width: 100%;
-  background-color: rgb(233, 227, 227);
   display: flex;
   flex-direction: column;
 }
 
-#inputs-container {
+#ui-server-container {
+  display: flex;
+  flex-direction: row;
+}
+
+#ui-server-selector {
+  width: 100%;
+  text-align: center;
+}
+
+#buttons-container {
   display: flex;
-  justify-content: space-between;
+  flex-direction: row;
+}
+
+#action-button {
+  flex: none;
 }
 
 #reload-button {
   flex: auto;
-  background-color: rgb(25, 118, 210);
   color: white;
-  font-size: 35px;
+  background-color: blue;
+  font-size: 1.5rem;
   font-weight: bold;
+  align-items: center;
+  justify-content: center;
 }
 
 #reload-button:hover {
-  background-color: rgb(10, 113, 195);
+  background-color: rgb(0, 0, 225);
 }
 
 #reload-button:active {
-  background-color: rgb(255, 113, 195);
+  background-color: red;
 }
 
-#simulator-button {
-  flex: auto;
-}
-
-#idtag-field {
-  flex: auto;
-  text-align: center;
+#action {
+  color: white;
+  background-color: black;
+  padding: 1%;
 }
 </style>